WPF学习-自定义控件库!

WPF自定义按钮,增加圆角样式功能!

  • 一、自定义控件库流程(以添加圆角属性为例)
    • 1.创建控件库项目
    • 2.控件.cs文件中添加边框圆角属性
    • 3.调用按键资源文件
    • 4.编辑MyButton.xaml文件,设置样式
      • vs默认的样式请参考:
      • 添加颜色资源
      • 设置默认样式
      • 绑定边框样式数据
    • 5.完整MyButton.xaml资源字典如下:
    • 6.生成dll
    • 7.新项目调用
  • 二、自定义ComboBox控件
    • 1.自定义控件编辑模板
    • 2.注意事项汇总
      • 自定义格式跨层级绑定外层控件的数据
      • 自定义下拉框样式后出现绑定数据DisplayMemberPath属性无效的情况
  • 附件:学习过程中参考的文档如下:
    • 1.自定义控件流程

一、自定义控件库流程(以添加圆角属性为例)

1.创建控件库项目

  1. 新建工程后,默认会有“Themes”文件加,用于保存控件样式。
  2. 右键项目选择添加新建项=> 选择WPF => 选择自定义控件(WPF)=> 输入控件名然后电机添加,创建控件。
  3. 右键项目选择添加资源字典(WPF)=> 输入控件名然后电机添加,创建资源字典。
  4. 创建完毕后的框架如下图:
    WPF学习-自定义控件库!_第1张图片

2.控件.cs文件中添加边框圆角属性

    public class MyButton : Button
    {
        static MyButton()
        {
            //                                              新创建的控件名                  模板名,资源字典(如MyButton.xaml),如果要跟旧的一样,直接填“Button”
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MyButton), new FrameworkPropertyMetadata(typeof(MyButton)));
        }

        /// 
        /// 按键圆角属性委托
        /// CornerRadius:用于调用的委托名字
        /// typeof(MyButton):指定控件
        /// 
        public static readonly DependencyProperty BorderRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(int), typeof(MyButton), new FrameworkPropertyMetadata());

        /// 
        /// 定义按钮圆角属性
        /// 
        public int CornerRadius
        {
            get { return (int)GetValue(BorderRadiusProperty); }
            set { SetValue(BorderRadiusProperty, value); }
        }
    }

3.调用按键资源文件

Generic.xaml中增加如下代码,调用资源文件MyButton.xaml

    <ResourceDictionary.MergedDictionaries>
        <!--引用按键资源字典-->
        <ResourceDictionary Source= "/MyWpfCustomControlLibrary;Component/Themes/MyButton.xaml"/>
    </ResourceDictionary.MergedDictionaries>

4.编辑MyButton.xaml文件,设置样式

vs默认的样式请参考:

Button 样式和模板

添加颜色资源

因为我将通用颜色

    <!--引用颜色资源-->
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source= "/MyWpfCustomControlLibrary;Component/Themes/ColorResource.xaml"/>
    </ResourceDictionary.MergedDictionaries>

设置默认样式

	//将设置默认添加时的样式
    <Style TargetType="local:MyButton">
        <Setter Property="SnapsToDevicePixels" Value="true" />
        <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}" />
        <Setter Property="MinHeight" Value="23" />
        <Setter Property="MinWidth" Value="75" />
        //...后续代码

绑定边框样式数据

在边框属性中,将边框的属性对控件属性进行绑定
其中:
CornerRadius="{Binding Path=CornerRadius,RelativeSource={RelativeSource TemplatedParent}}",中的CornerRadius 对应.cs文件中创建的委托名
其他属性直接调用的控件原来就有的属性

                        <Border TextBlock.Foreground="{TemplateBinding Foreground}"
                            x:Name="Border"
                            CornerRadius="{Binding Path=CornerRadius,RelativeSource={RelativeSource TemplatedParent}}"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                            //...

5.完整MyButton.xaml资源字典如下:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:MyWpfCustomControlLibrary"
                    xmlns:vsm="http://schemas.microsoft.com/netfx/2009/xaml/presentation">
   
    <!--引用颜色资源-->
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source= "/MyWpfCustomControlLibrary;Component/Themes/ColorResource.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    
    <!-- FocusVisual -->
    <Style x:Key="ButtonFocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>
                    <Border>
                        <Rectangle Margin="2"
                         StrokeThickness="1"
                         Stroke="#60000000"
                         StrokeDashArray="1 2" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- Button -->
    <Style TargetType="local:MyButton">
        <Setter Property="SnapsToDevicePixels" Value="true" />
        <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}" />
        <Setter Property="MinHeight" Value="23" />
        <Setter Property="MinWidth" Value="75" />
        
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid>
                        <Border TextBlock.Foreground="{TemplateBinding Foreground}"
                            x:Name="Border"
                            CornerRadius="{Binding Path=CornerRadius,RelativeSource={RelativeSource TemplatedParent}}"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">

                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualStateGroup.Transitions>
                                        <VisualTransition GeneratedDuration="0:0:0.5" />
                                        <VisualTransition GeneratedDuration="0"
                                      To="Pressed" />
                                    </VisualStateGroup.Transitions>
                                    <VisualState x:Name="Normal" />
                                    <VisualState x:Name="MouseOver">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
                          (GradientBrush.GradientStops)[1].(GradientStop.Color)"
                                                    Storyboard.TargetName="Border">
                                                <EasingColorKeyFrame KeyTime="0"
                                             Value="{StaticResource ControlMouseOverColor}" />
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Pressed">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
                          (GradientBrush.GradientStops)[1].(GradientStop.Color)"
                                                    Storyboard.TargetName="Border">
                                                <EasingColorKeyFrame KeyTime="0"
                                             Value="{StaticResource ControlPressedColor}" />
                                            </ColorAnimationUsingKeyFrames>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).
                          (GradientBrush.GradientStops)[0].(GradientStop.Color)"
                                                    Storyboard.TargetName="Border">
                                                <EasingColorKeyFrame KeyTime="0"
                                             Value="{StaticResource PressedBorderDarkColor}" />
                                            </ColorAnimationUsingKeyFrames>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).
                          (GradientBrush.GradientStops)[1].(GradientStop.Color)"
                                                    Storyboard.TargetName="Border">
                                                <EasingColorKeyFrame KeyTime="0"
                                             Value="{StaticResource PressedBorderLightColor}" />
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
                          (GradientBrush.GradientStops)[1].(GradientStop.Color)"
                                                    Storyboard.TargetName="Border">
                                                <EasingColorKeyFrame KeyTime="0"
                                             Value="{StaticResource DisabledControlDarkColor}" />
                                            </ColorAnimationUsingKeyFrames>
                                            <ColorAnimationUsingKeyFrames
                          Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
                                                    Storyboard.TargetName="Border">
                                                <EasingColorKeyFrame KeyTime="0"
                                             Value="{StaticResource DisabledForegroundColor}" />
                                            </ColorAnimationUsingKeyFrames>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).
                          (GradientBrush.GradientStops)[1].(GradientStop.Color)"
                                                    Storyboard.TargetName="Border">
                                                <EasingColorKeyFrame KeyTime="0"
                                             Value="{StaticResource DisabledBorderDarkColor}" />
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <ContentPresenter Margin="2"
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                RecognizesAccessKey="True" />
                        </Border>
                    </Grid>
                    
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsDefault" Value="true">
                            <Setter TargetName="Border"  Property="BorderBrush">
                                <Setter.Value>
                                    <LinearGradientBrush StartPoint="0,0"  EndPoint="0,1">
                                        <GradientBrush.GradientStops>
                                            <GradientStopCollection>
                                                <GradientStop Color="{DynamicResource DefaultBorderBrushLightBrush}"  Offset="0.0" />
                                                <GradientStop Color="{DynamicResource DefaultBorderBrushDarkColor}"  Offset="1.0" />
                                            </GradientStopCollection>
                                        </GradientBrush.GradientStops>
                                    </LinearGradientBrush>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                        
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        
    </Style>

</ResourceDictionary>

6.生成dll

点击生成=> 选择生成项目选项,生成

7.新项目调用

创建新项目,在新项目的引用项右键点击,添加引用
WPF学习-自定义控件库!_第2张图片
通过浏览,找到生成的.dll文件,然后将文件添加到系统中,然后系统工具箱会自动显示创建的控件,然后按照正常控件拖拽引用就可以。
WPF学习-自定义控件库!_第3张图片
拖拽引用后,xaml文件中会自动添加调用资源:

xmlns:MyWpfCustomControlLibrary="clr-namespace:MyWpfCustomControlLibrary;assembly=MyWpfCustomControlLibrary"

二、自定义ComboBox控件

1.自定义控件编辑模板

  • 组合框样式:编辑ComboBoxStyle
  • 下拉框样式:编辑ComboBoxItemStyle

2.注意事项汇总

自定义格式跨层级绑定外层控件的数据

使用查找绑定的方式绑定数据

CornerRadius="{Binding CornerRadius, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type local:UdComboBox}}}"

自定义下拉框样式后出现绑定数据DisplayMemberPath属性无效的情况

这种情况是由于绑定格式时作为内容显示的ContentPresenter没有设置ContentTemplateSelector属性引起的,绑定该属性后解决问题

 ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"

附件:学习过程中参考的文档如下:

1.自定义控件流程

  • WPF自定义控件 按钮 (一)
  • WPF 自定义TextBox带水印控件,可设置圆角

你可能感兴趣的:(XAML,自定义,控件操作)