程序员的资源宝库

网站首页 > gitee 正文

WPF 使用附加属性增加控件属性(wpf 附加行为)

sanyeah 2024-04-01 11:43:16 gitee 3 ℃ 0 评论

使用附加属性增加控件属性,使得这个附加属性在使用的时候没有局限性,可以在任何的控件中使用它来增加所需要的属性,使得控件的属性使用起来非常灵活

 

一、自定义附加属性

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>

  

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表