该自定义搜索控件继承TextBox,并且又添加了6种自定义依赖属性,分别为
Hint:暗示输入类型
MinCharacts:检验最少输入字符,如果小于该值则不能执行搜索命令
Text:该值重写了TextBox的Text属性,并且可以及时更新Text值,而不是等到失去焦点的时候才去更新
ErrorMessage:错误信息,当检验不符合条件时候在右下方显示error信息
HighLightBorderBrush:当有错误信息时候,给SearchBox添加指定颜色的边框
Command:按回车键时候,当验证通过时候执行搜索命令
效果图
SearchBox.cs 依赖属性声明:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace CommonUI.CustomControls
{
/// <summary>
/// A custom search control
/// </summary>
public class SearchBox : TextBox
{
private ContentControl HintContent;
private TextBlock ErrorContent;
public static readonly DependencyProperty HintProperty =
DependencyProperty.Register("Hint", typeof(string), typeof(SearchBox), new PropertyMetadata(OnHintPropertyChanged));
public static readonly DependencyProperty MinCharactersPerperty =
DependencyProperty.Register("MinCharacters", typeof(int), typeof(SearchBox), new PropertyMetadata(0));
public static readonly new DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(SearchBox), new PropertyMetadata(default(string), OnTextChanged));
public static readonly new DependencyProperty ErrorMessageProperty =
DependencyProperty.Register("ErrorMessage", typeof(string), typeof(SearchBox), new PropertyMetadata(null));
public static readonly new DependencyProperty HighLightBorderBrushProperty =
DependencyProperty.Register("HighLightBorderBrush", typeof(Brush), typeof(SearchBox), new PropertyMetadata(null));
public static readonly new DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(SearchBox), null);
#region Properties fields
/// <summary>
/// Get and set methods for the Text dependency property value.
/// so that the value can update immediately
/// </summary>
public new string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
/// <summary>
/// Get and set methods for the ErrorMessage dependency Property value.
/// </summary>
public string ErrorMessage
{
get { return (string)GetValue(ErrorMessageProperty); }
set { SetValue(ErrorMessageProperty, value); }
}
/// <summary>
/// Get and set methods for the HighLightBorderBrush dependency property value.
/// </summary>
public Brush HighLightBorderBrush
{
get { return (Brush)GetValue(HighLightBorderBrushProperty); }
set { SetValue(HighLightBorderBrushProperty, value); }
}
/// <summary>
/// Get and set methods for the Hint dependency property value.
/// </summary>
public string Hint
{
get { return (string)GetValue(HintProperty); }
set { this.SetValue(HintProperty, value); }
}
/// <summary>
/// Get and set methods for the MinCharacters dependency property value.
/// the default value is 0, if the value is bigger than 0, the control will check the length and show the highlight border
/// </summary>
public int MinCharacters
{
get { return (int)this.GetValue(MinCharactersPerperty); }
set { this.SetValue(MinCharactersPerperty, value); }
}
/// <summary>
/// Get and set methods for the Command dependency property value.
/// Command triggered when the KeyUp with the ENTER key occurs.
/// </summary>
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
#endregion
public SearchBox()
{
DefaultStyleKey = this.GetType();
base.TextChanged += (s, e) =>
{
Text = base.Text;
};
}
#region Override methods
protected override void OnKeyUp(KeyEventArgs e)
{
if (!string.IsNullOrEmpty(this.Text))
{
if (e.Key == Key.Enter && this.Text.Length >= this.MinCharacters)
{
this.Command.Execute(this.Text);
}
if (e.Key == Key.Unknown && this.Text.Length >= this.MinCharacters)
{
if (e.PlatformKeyCode == 10)
{
this.Command.Execute(this.Text);
}
}
}
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.HintContent = this.GetTemplateChild("hintContent") as ContentControl;
this.ErrorContent = this.GetTemplateChild("errorContent") as TextBlock;
if (ErrorContent != null)
{
HideErrorContent(true);
}
if (HintContent != null)
{
DetermineHintContentVisibility();
}
}
protected override void OnGotFocus(RoutedEventArgs e)
{
if (HintContent != null && string.IsNullOrEmpty(this.Text))
{
this.HintContent.Visibility = Visibility.Collapsed;
}
if (((SolidColorBrush)this.BorderBrush).Color == Color.FromArgb(191, 255, 255, 255))
{
this.BorderBrush = new SolidColorBrush(Colors.White);
}
base.OnGotFocus(e);
}
protected override void OnLostFocus(RoutedEventArgs e)
{
if (HintContent != null && string.IsNullOrEmpty(this.Text))
{
this.HintContent.Visibility = Visibility.Visible;
this.ClearValue(BorderBrushProperty);
HideErrorContent(true);
}
if (((SolidColorBrush)this.BorderBrush).Color == Colors.White)
{
this.ClearValue(BorderBrushProperty);
}
base.OnLostFocus(e);
}
#endregion
#region Private methods
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SearchBox txt = d as SearchBox;
txt.Text = (string)e.NewValue;
if (txt.Text.Length < (int)d.GetValue(MinCharactersPerperty))
{
txt.BorderBrush = txt.GetValue(HighLightBorderBrushProperty) as Brush;
txt.HideErrorContent(false);
}
else
{
if ((int)d.GetValue(MinCharactersPerperty) != 0)
{
txt.HideErrorContent(true);
txt.BorderBrush = new SolidColorBrush(Colors.White);
}
}
}
private static void OnHintPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
SearchBox textBox = sender as SearchBox;
if (textBox != null && textBox.HintContent != null)
{
textBox.DetermineHintContentVisibility();
}
}
private void HideErrorContent(bool hide)
{
this.ErrorContent.Visibility = hide ? Visibility.Collapsed : Visibility.Visible;
}
private void DetermineHintContentVisibility()
{
if (string.IsNullOrEmpty(this.Text))
{
this.HintContent.Visibility = Visibility.Visible;
}
else
{
this.HintContent.Visibility = Visibility.Collapsed;
}
}
#endregion
}
}
Style:SearchBox.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:local="clr-namespace:CommonUI.CustomControls">
<Style TargetType="local:SearchBox">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
<Setter Property="Background" Value="{StaticResource PhoneTextBoxBrush}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneTextBoxForegroundBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource PhoneTextBoxBrush}"/>
<Setter Property="SelectionBackground" Value="{StaticResource PhoneAccentBrush}"/>
<Setter Property="SelectionForeground" Value="{StaticResource PhoneTextBoxSelectionForegroundBrush}"/>
<Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:SearchBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="EnabledBorder">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DisabledOrReadonlyBorder">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ReadOnly">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="EnabledBorder">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DisabledOrReadonlyBorder">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="DisabledOrReadonlyBorder">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="DisabledOrReadonlyBorder">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="DisabledOrReadonlyContent">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxReadOnlyBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="EnabledBorder">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBackgroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Background="Transparent" Grid.Row="0" Margin="{TemplateBinding Margin}">
<Border x:Name="EnabledBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="{StaticResource PhoneTouchTargetOverhang}">
<Grid>
<ContentControl x:Name="hintContent" Content="{TemplateBinding Hint}" HorizontalAlignment="Left" Background="Transparent" Opacity="0.5"/>
<ContentControl x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch" Margin="{StaticResource PhoneTextBoxInnerMargin}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>
</Grid>
</Border>
<Border x:Name="DisabledOrReadonlyBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent" Margin="{StaticResource PhoneTouchTargetOverhang}" Visibility="Collapsed">
<TextBox x:Name="DisabledOrReadonlyContent" Background="Transparent" Foreground="{StaticResource PhoneDisabledBrush}"
FontWeight="{TemplateBinding FontWeight}" FontStyle="{TemplateBinding FontStyle}" FontSize="{TemplateBinding FontSize}"
FontFamily="{TemplateBinding FontFamily}" IsReadOnly="True" SelectionForeground="{TemplateBinding SelectionForeground}"
SelectionBackground="{TemplateBinding SelectionBackground}" TextAlignment="{TemplateBinding TextAlignment}"
Height="{TemplateBinding Height}" Width="{TemplateBinding Width}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}"
TextWrapping="{TemplateBinding TextWrapping}" Text="{TemplateBinding Text}"/>
</Border>
</Grid>
<TextBlock x:Name="errorContent" Grid.Row="1" Text="{TemplateBinding ErrorMessage}" Style="{StaticResource ErrorContentStyle}" Foreground="{TemplateBinding HighLightBorderBrush}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="TextBlock" x:Key="ErrorContentStyle">
<Setter Property="Margin" Value="0,-10,10,0"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
</ResourceDictionary>
页面
<local:SearchBox Hint="{Binding User.CustomerSearchHint, Source={StaticResource LocalizationManager}}" x:Name="searchBorder" Padding="5" MinCharacters="3" HighLightBorderBrush="Red" BorderThickness="3" HorizontalAlignment="Stretch" Text="{Binding SearchString, Mode=TwoWay}" ErrorMessage="{Binding User.ErrorSearchString, Source={StaticResource LocalizationManager}}" Command="{Binding SearchCommand}"/>
本文介绍了一种基于TextBox自定义的搜索控件,新增了六种依赖属性,包括Hint、MinCharacters、Text、ErrorMessage、HighLightBorderBrush和Command。文章详细展示了控件的功能特性、依赖属性设置及样式模板。
660

被折叠的 条评论
为什么被折叠?



