diff --git a/HandyControl/Controls/Input/ComboBox.cs b/HandyControl/Controls/Input/ComboBox.cs index 3eb05716..7d6baf16 100644 --- a/HandyControl/Controls/Input/ComboBox.cs +++ b/HandyControl/Controls/Input/ComboBox.cs @@ -33,7 +33,7 @@ namespace HandyControl.Controls /// 数据是否错误 /// public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register( - "IsError", typeof(bool), typeof(ComboBox), new PropertyMetadata(default(bool))); + "IsError", typeof(bool), typeof(ComboBox), new PropertyMetadata(ValueBoxes.FalseBox)); public bool IsError { @@ -72,7 +72,7 @@ namespace HandyControl.Controls /// 是否显示清除按钮 /// public static readonly DependencyProperty ShowClearButtonProperty = DependencyProperty.Register( - "ShowClearButton", typeof(bool), typeof(ComboBox), new PropertyMetadata(default(bool))); + "ShowClearButton", typeof(bool), typeof(ComboBox), new PropertyMetadata(ValueBoxes.FalseBox)); public bool ShowClearButton { diff --git a/HandyControl/Controls/Input/PasswordBox.cs b/HandyControl/Controls/Input/PasswordBox.cs index 392fda2e..8d7708e2 100644 --- a/HandyControl/Controls/Input/PasswordBox.cs +++ b/HandyControl/Controls/Input/PasswordBox.cs @@ -27,7 +27,7 @@ namespace HandyControl.Controls /// 数据是否错误 /// public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register( - "IsError", typeof(bool), typeof(PasswordBox), new PropertyMetadata(default(bool))); + "IsError", typeof(bool), typeof(PasswordBox), new PropertyMetadata(ValueBoxes.FalseBox)); /// /// 错误提示 @@ -45,7 +45,7 @@ namespace HandyControl.Controls /// 是否显示清除按钮 /// public static readonly DependencyProperty ShowClearButtonProperty = DependencyProperty.Register( - "ShowClearButton", typeof(bool), typeof(PasswordBox), new PropertyMetadata(default(bool))); + "ShowClearButton", typeof(bool), typeof(PasswordBox), new PropertyMetadata(ValueBoxes.FalseBox)); private string _password; diff --git a/HandyControl/Controls/Input/SearchBar.cs b/HandyControl/Controls/Input/SearchBar.cs new file mode 100644 index 00000000..cc19ed54 --- /dev/null +++ b/HandyControl/Controls/Input/SearchBar.cs @@ -0,0 +1,175 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Input; +using HandyControl.Data; +using HandyControl.Interactivity; +using HandyControl.Tools; + +namespace HandyControl.Controls +{ + [TemplatePart(Name = ElementTextBox, Type = typeof(WatermarkTextBox))] + public class SearchBar : Control, IDataInput + { + private const string ElementTextBox = "PART_TextBox"; + + private WatermarkTextBox _textBox; + + public Func> VerifyFunc { get; set; } + + public SearchBar() + { + CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) => + { + _textBox.Text = string.Empty; + })); + CommandBindings.Add(new CommandBinding(ControlCommands.Search, (s, e) => + { + RaiseEvent(new FunctionEventArgs(SearchStartedEvent, this) + { + Source = Text + }); + })); + } + + public static readonly RoutedEvent SearchStartedEvent = + EventManager.RegisterRoutedEvent("SearchStarted", RoutingStrategy.Direct, + typeof(EventHandler>), typeof(SearchBar)); + + public event EventHandler> SearchStarted + { + add => AddHandler(SearchStartedEvent, value); + remove => RemoveHandler(SearchStartedEvent, value); + } + + public override void OnApplyTemplate() + { + if (_textBox != null) + { + _textBox.TextChanged -= TextBox_TextChanged; + } + + base.OnApplyTemplate(); + + _textBox = GetTemplateChild(ElementTextBox) as WatermarkTextBox; + if (_textBox != null) + { + SetBinding(TextProperty, new Binding(TextProperty.Name) + { + Source = _textBox, + Mode = BindingMode.TwoWay, + UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged + }); + _textBox.TextChanged += TextBox_TextChanged; + _textBox.KeyDown += TextBox_KeyDown; + } + } + + private void TextBox_KeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + RaiseEvent(new FunctionEventArgs(SearchStartedEvent, this) + { + Source = Text + }); + } + } + + private void TextBox_TextChanged(object sender, TextChangedEventArgs e) => VerifyData(); + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register( + "Text", typeof(string), typeof(SearchBar), new PropertyMetadata(default(string))); + + public string Text + { + get => (string) GetValue(TextProperty); + set => SetValue(TextProperty, value); + } + + /// + /// 数据是否错误 + /// + public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register( + "IsError", typeof(bool), typeof(SearchBar), new PropertyMetadata(ValueBoxes.FalseBox)); + + public bool IsError + { + get => (bool)GetValue(IsErrorProperty); + set => SetValue(IsErrorProperty, value); + } + + /// + /// 错误提示 + /// + public static readonly DependencyProperty ErrorStrProperty = DependencyProperty.Register( + "ErrorStr", typeof(string), typeof(SearchBar), new PropertyMetadata(default(string))); + + public string ErrorStr + { + get => (string)GetValue(ErrorStrProperty); + set => SetValue(ErrorStrProperty, value); + } + + /// + /// 文本类型 + /// + public static readonly DependencyProperty TextTypeProperty = DependencyProperty.Register( + "TextType", typeof(TextType), typeof(SearchBar), new PropertyMetadata(default(TextType))); + + public TextType TextType + { + get => (TextType) GetValue(TextTypeProperty); + set => SetValue(TextTypeProperty, value); + } + + /// + /// 是否显示清除按钮 + /// + public static readonly DependencyProperty ShowClearButtonProperty = DependencyProperty.Register( + "ShowClearButton", typeof(bool), typeof(SearchBar), new PropertyMetadata(ValueBoxes.FalseBox)); + + public bool ShowClearButton + { + get => (bool)GetValue(ShowClearButtonProperty); + set => SetValue(ShowClearButtonProperty, value); + } + + public virtual bool VerifyData() + { + OperationResult result; + + if (VerifyFunc != null) + { + result = VerifyFunc.Invoke(Text); + } + else + { + if (!string.IsNullOrEmpty(Text)) + { + if (TextType != TextType.Common) + { + result = Text.IsKindOf(TextType) ? OperationResult.Success() : OperationResult.Failed(Properties.Langs.Lang.FormatError); + } + else + { + result = OperationResult.Success(); + } + } + else if (InfoElement.GetNecessary(this)) + { + result = OperationResult.Failed(Properties.Langs.Lang.IsNecessary); + } + else + { + result = OperationResult.Success(); + } + } + + IsError = !result.Data; + ErrorStr = result.Message; + return result.Data; + } + } +} \ No newline at end of file diff --git a/HandyControl/HandyControl.csproj b/HandyControl/HandyControl.csproj index ef651cad..fcc5cbc6 100644 --- a/HandyControl/HandyControl.csproj +++ b/HandyControl/HandyControl.csproj @@ -49,6 +49,7 @@ + @@ -267,6 +268,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -479,6 +484,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/HandyControl/Interactivity/ControlCommands.cs b/HandyControl/Interactivity/ControlCommands.cs index 2f57807a..e74368fc 100644 --- a/HandyControl/Interactivity/ControlCommands.cs +++ b/HandyControl/Interactivity/ControlCommands.cs @@ -7,6 +7,11 @@ namespace HandyControl.Interactivity /// public static class ControlCommands { + /// + /// 搜索 + /// + public static RoutedCommand Search { get; } = new RoutedCommand(nameof(Search), typeof(ControlCommands)); + /// /// 清除 /// diff --git a/HandyControl/Themes/Styles/Base/SearchBarBaseStyle.xaml b/HandyControl/Themes/Styles/Base/SearchBarBaseStyle.xaml new file mode 100644 index 00000000..8a6cd520 --- /dev/null +++ b/HandyControl/Themes/Styles/Base/SearchBarBaseStyle.xaml @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +