使用附加属性增加控件属性,使得这个附加属性在使用的时候没有局限性,可以在任何的控件中使用它来增加所需要的属性,使得控件的属性使用起来非常灵活
一、自定义附加属性
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Demo3.Control
{
public class ControlAttachProperty
{
#region 圆角
public static CornerRadius GetCornerRadius(DependencyObject obj)
{
return (CornerRadius)obj.GetValue(CornerRadiusProperty);
}
public static void SetCornerRadius(DependencyObject obj, CornerRadius value)
{
obj.SetValue(CornerRadiusProperty, value);
}
// Using a DependencyProperty as the backing store for CornerRadius. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.RegisterAttached("CornerRadius", typeof(CornerRadius), typeof(ControlAttachProperty), new PropertyMetadata(null));
#endregion
#region 用户头像模板
public static ControlTemplate GetIconTemplate(DependencyObject obj)
{
return (ControlTemplate)obj.GetValue(IconTemplateProperty);
}
public static void SetIconTemplate(DependencyObject obj, ControlTemplate value)
{
obj.SetValue(IconTemplateProperty, value);
}
// Using a DependencyProperty as the backing store for IconTemplate. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IconTemplateProperty =
DependencyProperty.RegisterAttached("IconTemplate", typeof(ControlTemplate), typeof(ControlAttachProperty), new PropertyMetadata(null));
#endregion
#region 删除按妞区域模板
public static ControlTemplate GetAttachTemplate(DependencyObject obj)
{
return (ControlTemplate)obj.GetValue(AttachTemplateProperty);
}
public static void SetAttachTemplate(DependencyObject obj, ControlTemplate value)
{
obj.SetValue(AttachTemplateProperty, value);
}
// Using a DependencyProperty as the backing store for AttachTemplate. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AttachTemplateProperty =
DependencyProperty.RegisterAttached("AttachTemplate", typeof(ControlTemplate), typeof(ControlAttachProperty), new PropertyMetadata(null));
#endregion
#region 用户名水印
public static string GetUserNameWaterMark(DependencyObject obj)
{
return (string)obj.GetValue(UserNameWaterMarkProperty);
}
public static void SetUserNameWaterMark(DependencyObject obj, string value)
{
obj.SetValue(UserNameWaterMarkProperty, value);
}
// Using a DependencyProperty as the backing store for UserNameWaterMark. This enables animation, styling, binding, etc...
public static readonly DependencyProperty UserNameWaterMarkProperty =
DependencyProperty.RegisterAttached("UserNameWaterMark", typeof(string), typeof(ControlAttachProperty), new PropertyMetadata(null));
#endregion
#region 密码水印
public static string GetPasswordWaterMark(DependencyObject obj)
{
return (string)obj.GetValue(PasswordWaterMarkProperty);
}
public static void SetPasswordWaterMark(DependencyObject obj, string value)
{
obj.SetValue(PasswordWaterMarkProperty, value);
}
// Using a DependencyProperty as the backing store for PasswordWaterMark. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PasswordWaterMarkProperty =
DependencyProperty.RegisterAttached("PasswordWaterMark", typeof(string), typeof(ControlAttachProperty), new PropertyMetadata(null));
#endregion
#region 用户头像(未被点击时)
public static string GetUserIcon(DependencyObject obj)
{
return (string)obj.GetValue(UserIconProperty);
}
public static void SetUserIcon(DependencyObject obj, string value)
{
obj.SetValue(UserIconProperty, value);
}
// Using a DependencyProperty as the backing store for UserIcon. This enables animation, styling, binding, etc...
public static readonly DependencyProperty UserIconProperty =
DependencyProperty.RegisterAttached("UserIcon", typeof(string), typeof(ControlAttachProperty), new PropertyMetadata(null));
#endregion
#region 用户头像(点击时)
public static string GetUserIconPress(DependencyObject obj)
{
return (string)obj.GetValue(UserIconPressProperty);
}
public static void SetUserIconPress(DependencyObject obj, string value)
{
obj.SetValue(UserIconPressProperty, value);
}
// Using a DependencyProperty as the backing store for UserIconPress. This enables animation, styling, binding, etc...
public static readonly DependencyProperty UserIconPressProperty =
DependencyProperty.RegisterAttached("UserIconPress", typeof(string), typeof(ControlAttachProperty), new PropertyMetadata(null));
#endregion
#region 密码图标(未被点击时)
public static string GetPassWordIcon(DependencyObject obj)
{
return (string)obj.GetValue(PassWordIconProperty);
}
public static void SetPassWordIcon(DependencyObject obj, string value)
{
obj.SetValue(PassWordIconProperty, value);
}
// Using a DependencyProperty as the backing store for PassWordIcon. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PassWordIconProperty =
DependencyProperty.RegisterAttached("PassWordIcon", typeof(string), typeof(ControlAttachProperty), new PropertyMetadata(null));
#endregion
#region 密码图标(点击时)
public static string GetPasswordIconPress(DependencyObject obj)
{
return (string)obj.GetValue(PasswordIconPressProperty);
}
public static void SetPasswordIconPress(DependencyObject obj, string value)
{
obj.SetValue(PasswordIconPressProperty, value);
}
// Using a DependencyProperty as the backing store for PasswordIconPress. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PasswordIconPressProperty =
DependencyProperty.RegisterAttached("PasswordIconPress", typeof(string), typeof(ControlAttachProperty), new PropertyMetadata(null));
#endregion
#region 删除按妞背景图片
public static ImageBrush GetDeleteButtonBG(DependencyObject obj)
{
return (ImageBrush)obj.GetValue(DeleteButtonBGProperty);
}
public static void SetDeleteButtonBG(DependencyObject obj, ImageBrush value)
{
obj.SetValue(DeleteButtonBGProperty, value);
}
// Using a DependencyProperty as the backing store for DeleteButtonBG. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DeleteButtonBGProperty =
DependencyProperty.RegisterAttached("DeleteButtonBG", typeof(ImageBrush), typeof(ControlAttachProperty), new PropertyMetadata(null));
#endregion
#region 定义是否开启绑定事件
public static bool GetIsCommandClearTextEvent(DependencyObject obj)
{
return (bool)obj.GetValue(IsCommandClearTextEventProperty);
}
public static void SetIsCommandClearTextEvent(DependencyObject obj, bool value)
{
obj.SetValue(IsCommandClearTextEventProperty, value);
}
// Using a DependencyProperty as the backing store for IsCommandClearTextEvent. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsCommandClearTextEventProperty =
DependencyProperty.RegisterAttached("IsCommandClearTextEvent", typeof(bool), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(false,IsCommandClearTextEventChanged));
private static void IsCommandClearTextEventChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
}
#endregion
#region 是否显示密码样式
public static bool GetIsVisiblityPassword(DependencyObject obj)
{
return (bool)obj.GetValue(IsVisiblityPasswordProperty);
}
public static void SetIsVisiblityPassword(DependencyObject obj, bool value)
{
obj.SetValue(IsVisiblityPasswordProperty, value);
}
// Using a DependencyProperty as the backing store for IsVisiblityPassword. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsVisiblityPasswordProperty =
DependencyProperty.RegisterAttached("IsVisiblityPassword", typeof(bool), typeof(ControlAttachProperty), new PropertyMetadata(false));
#endregion
#region 清除事件命令
public static bool GetIsClearTextButtonBehaviorEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsClearTextButtonBehaviorEnabledProperty);
}
public static void SetIsClearTextButtonBehaviorEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsClearTextButtonBehaviorEnabledProperty, value);
}
// Using a DependencyProperty as the backing store for IsClearTextButtonBehaviorEnabled. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsClearTextButtonBehaviorEnabledProperty =
DependencyProperty.RegisterAttached("IsClearTextButtonBehaviorEnabled", typeof(bool), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(false,IsClearTextButtonBehaviorEnabledChanged));
/// <summary>
/// 当附加属性值发生改变时,调用此方法
/// </summary>
/// <param name="d"></param>
/// <param name="e"></param>
private static void IsClearTextButtonBehaviorEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var button=d as DeleteButton;
if(e.OldValue != e.NewValue)
{
//当命令触发的时候,会向上传递,而此时这个命令外围就是自己本身
button.CommandBindings.Add(ClearTextCommandBinding);
}
}
/**
* 当命令触发的时候,会一级一级向上传递,当传递到命令关联者时,会处理这个命令
*/
/// <summary>
/// 创建一个命令
/// </summary>
public static RoutedUICommand ClearTextCommand{get;private set;}
/// <summary>
/// 命令绑定关联
/// </summary>
private static readonly CommandBinding ClearTextCommandBinding;
private static void ClearButtonClick(object sender,ExecutedRoutedEventArgs e)
{
var tbox=e.Parameter as FrameworkElement;
if(tbox==null) return;
if(tbox is TextBox)
{
((TextBox)tbox).Clear();
}
tbox.Focus();
}
#endregion
static ControlAttachProperty()
{
ClearTextCommand = new RoutedUICommand();
ClearTextCommandBinding =new CommandBinding();
//将者命令加入到这个命令关联中,如果某个控件调用了这个命令,只要他所在的层级中有关联这个命令关联对象,那么这个命令对象就会对其进行处理
ClearTextCommandBinding.Command = ClearTextCommand;
ClearTextCommandBinding.Executed+=ClearButtonClick;
}
}
}
在布局文件中使用它
<Window x:Class="Demo3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:Demo3.Control"
Background="Black"
Title="MainWindow"
WindowStartupLocation="CenterScreen"
Height="350"
Width="525">
<StackPanel>
<TextBox x:Name="UserName"
Width="230"
Height="38"
Margin="0,20,0,0"
FontSize="18"
VerticalContentAlignment="Center"
c:ControlAttachProperty.CornerRadius="5"
c:ControlAttachProperty.UserNameWaterMark="用户名"
c:ControlAttachProperty.UserIcon="{StaticResource UserName_BG}"
c:ControlAttachProperty.UserIconPress="{StaticResource UserName_BG_Press}"
c:ControlAttachProperty.DeleteButtonBG="{StaticResource Delete_Button_BG}"
c:ControlAttachProperty.IsVisiblityPassword="false"
Style="{StaticResource IconClearButtonTextBox}" />
<TextBox x:Name="Password"
Width="230"
Height="38"
Margin="0,20,0,0"
FontSize="18"
VerticalContentAlignment="Center"
c:ControlAttachProperty.CornerRadius="5"
c:ControlAttachProperty.UserNameWaterMark="密码"
c:ControlAttachProperty.UserIcon="{StaticResource Password_BG}"
c:ControlAttachProperty.UserIconPress="{StaticResource Password_BG_Press}"
c:ControlAttachProperty.DeleteButtonBG="{StaticResource Delete_Button_BG}"
c:ControlAttachProperty.IsVisiblityPassword="true"
Style="{StaticResource IconClearButtonTextBox}" />
</StackPanel>
</Window>
在style文件中进行使用
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:c="clr-namespace:Demo3.Control"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Demo3;component/Resources/Style/DeleteButton.xaml" />
</ResourceDictionary.MergedDictionaries>
<!--TextBox默认样式-->
<Style x:Key="DefaultTextBox" TargetType="{x:Type TextBox}">
<Setter Property="ContextMenu" Value="{DynamicResource TextBoxContextMenu}" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="Bg"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
CornerRadius="{TemplateBinding c:ControlAttachProperty.CornerRadius}"
Background="White"
BorderBrush="Transparent"
BorderThickness="0">
<Grid x:Name="PART_InnerGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition />
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<!--用户头像区域-->
<ContentControl x:Name="UserIcon"
Grid.Column="0"
Margin="5"
Template="{TemplateBinding c:ControlAttachProperty.IconTemplate}"
Focusable="False" />
<!--文本和水印-->
<ScrollViewer x:Name="PART_ContentHost"
BorderThickness="0"
Grid.Column="1"
IsTabStop="False"
Margin="2"
VerticalAlignment="Stretch"
Background="{x:Null}" />
<TextBlock x:Name="WaterMark"
Grid.Column="1"
VerticalAlignment="Center"
Foreground="Silver"
FontSize="18"
Text="{TemplateBinding c:ControlAttachProperty.UserNameWaterMark}"
Visibility="Collapsed"
Padding="5,0,0,0" />
<!-- 删除按钮-->
<ContentControl x:Name="DeleteIcon"
Grid.Column="2"
Width="15"
Height="15"
Margin="0,5,10,5"
Visibility="Visible"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Template="{TemplateBinding c:ControlAttachProperty.AttachTemplate}"
Focusable="False" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<!--当Text为空时,隐藏删除按钮-->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Text}" Value="">
<Setter Property="Visibility" TargetName="DeleteIcon" Value="Collapsed" />
<Setter Property="Visibility" TargetName="WaterMark" Value="Visible" />
</DataTrigger>
<!--是否显示密码样式-->
<Trigger Property="c:ControlAttachProperty.IsVisiblityPassword" Value="True">
<Setter Property="Height" Value="30"/>
<Setter Property="Foreground" Value="Transparent"></Setter>
<Setter Property="FontSize" Value="20"></Setter>
<Setter Property="FontFamily" Value="Courier New"></Setter>
<Setter Property="TextDecorations">
<Setter.Value>
<TextDecorationCollection>
<TextDecoration>
<TextDecoration.Pen>
<Pen Thickness="10"
Brush="Black"
EndLineCap="Round"
StartLineCap="Round"
DashCap="Round" >
<Pen.DashStyle>
<DashStyle Dashes="0.0,1.2" Offset="0.6"/>
</Pen.DashStyle>
</Pen>
</TextDecoration.Pen>
<TextDecoration.Location>
<TextDecorationLocation>Strikethrough</TextDecorationLocation>
</TextDecoration.Location>
</TextDecoration>
</TextDecorationCollection>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--TextBox包含附加属性Icon,以及ClearText按钮的样式-->
<Style x:Key="IconClearButtonTextBox" TargetType="{x:Type TextBox}" BasedOn="{StaticResource DefaultTextBox}">
<!--设置用户头像模板-->
<Setter Property="c:ControlAttachProperty.IconTemplate">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid>
<Image x:Name="Bg_HP"
Source="{Binding Path=(c:ControlAttachProperty.UserIcon),RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TextBox}}}"
Visibility="Visible"/>
<Image x:Name="Bg_HP_Press"
Source="{Binding Path=(c:ControlAttachProperty.UserIconPress),RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TextBox}}}"
Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsFocused, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}" Value="true">
<Setter Property="Visibility" TargetName="Bg_HP" Value="Collapsed" />
<Setter Property="Visibility" TargetName="Bg_HP_Press" Value="Visible" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<!--设置删除按妞模板-->
<Setter Property="c:ControlAttachProperty.AttachTemplate">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<c:DeleteButton ButtonBG="{Binding Path=(c:ControlAttachProperty.DeleteButtonBG),RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TextBox}}}"
BorderBrush="Transparent"
Style="{StaticResource DeleteButtonStyle}"
BorderThickness="0"
x:Name="CleanButton"
c:ControlAttachProperty.IsClearTextButtonBehaviorEnabled="True"
Command="c:ControlAttachProperty.ClearTextCommand"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"
Focusable="false" />
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Text,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}" Value="">
<Setter Property="Visibility" TargetName="CleanButton" Value="Collapsed" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>