WPF 附加属性+控件模板,完成自定义控件。建议观看HandyControl源码

news/2024/5/20 2:58:13 标签: wpf, hadoop, hdfs

文章目录

  • 相关连接
  • 前言
  • 需要实现的效果
  • 附加属性
    • 添加附加属性,以Test修改FontSize为例
    • 依赖属性使用
      • 触发器使用
      • 直接操控
    • 结论
  • 控件模板,在HandyControl的基础上面进行修改
    • 参考HandyControl的源码
    • 控件模板原型
    • 控件模板
  • 结论

相关连接

WPF控件模板(6)

WPF 附加属性

WPF教程:附加属性

前言

今天说服了领导用WPF开发前端,原因就是开发相对来说比较方便,写小项目就不用前后端分离什么的了。反正就是有个机会写WPF了,真开心。我已经写了一年的Uniapp了

需要实现的效果

就是想写一个简单的变色控件。
在这里插入图片描述

附加属性

如果想知道附加属性,就得先了解依赖属性。详细的可以看我这篇文章

WPF 用户控件依赖属性赋值

添加附加属性,以Test修改FontSize为例

知道了依赖属性之后,我解释一下附加属性是什么意思。附加属性就是为了方便在原有的控件基础上面进行细微的修改。我们先保证编译通过

附加属性的快捷键是propa

简单给TextBox添加一个附加属性

    public partial class TextBlockExtension
    {



        public static int GetTest(DependencyObject obj)
        {
            return (int)obj.GetValue(TestProperty);
        }

        public static void SetTest(DependencyObject obj, int value)
        {
            obj.SetValue(TestProperty, value);
        }

        // Using a DependencyProperty as the backing store for Test.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TestProperty =
            DependencyProperty.RegisterAttached("Test", typeof(int), typeof(TextBox), new PropertyMetadata(10));
        
        
    }

这样我们就能编译通过了。

<TextBlock Text="用户"  wpfEx:TextBlockExtension.Test="2"/>

在这里插入图片描述

依赖属性使用

依赖属性有两种使用方法

触发器使用

样式定义

    <!--一个简单的FontSize修改-->
    <Style x:Key="UserSelection"
           TargetType="TextBlock">
        <!--因为Triggers只有等于判断,所以这里简单写了一下-->
        <Style.Triggers>
            <Trigger Property="wpfEx:TextBlockExtension.Test"
                     Value="10">
                <Setter Property="FontSize"
                        Value="10" />
            </Trigger>
            <Trigger Property="wpfEx:TextBlockExtension.Test"
                     Value="20">
                <Setter Property="FontSize"
                        Value="20" />
            </Trigger>
        </Style.Triggers>
    </Style>

简单使用

 <TextBlock Text="用户"
            wpfEx:TextBlockExtension.Test="10" Style="{StaticResource UserSelection}">
     
 </TextBlock>
 <TextBlock Text="用户"
            wpfEx:TextBlockExtension.Test="20"
            Style="{StaticResource UserSelection}">
 </TextBlock>

在这里插入图片描述

直接操控

附加属性修改

//如果想直接操控元素,得在PropertyMetadata进行操控。记得设置初始值
public static readonly DependencyProperty TestProperty =
    DependencyProperty.RegisterAttached("Test", typeof(int), typeof(TextBox), new PropertyMetadata(10,(s, e) =>
    {
        //s是控件本身,
        var mdp = s as TextBlock;
        //如果控件是该元素的父组件,类似于Grid和DockPanel,就使用Parent来寻找,这里不展开
        //var mdpParent = (s as FrameworkElement).Parent as TextBlock;
        if (mdp != null && e.NewValue != null)
        {
            mdp.FontSize = (int)e.NewValue;
        }
    }));
<!--如果想要预览生效需要重新编译一下-->
<TextBlock Text="用户"
           wpfEx:TextBlockExtension.Test="15">

</TextBlock>
<TextBlock Text="用户"
           wpfEx:TextBlockExtension.Test="20">
</TextBlock>
<!--因为我们设置了默认值为10,所以这里是10-->
<TextBlock Text="用户">
</TextBlock>
<!--优先级还是依赖属性高,所以这里是30而不是默认值10-->
<TextBlock Text="用户" FontSize="30">
</TextBlock>

在这里插入图片描述

结论

附加属性和依赖属性差不多,就是声明麻烦一点。因为Get,Set是需要额外写的。

控件模板,在HandyControl的基础上面进行修改

控件模板一般用于按钮,我们只要会按钮的控件模板就可以了。

WPF控件模板(6)

参考HandyControl的源码

HandyControl 页面

HandyControl的Button有IconButton的样式源码。看一下还是挺有收获的。

在这里插入图片描述
参考样式代码

 <Style x:Key="ButtonDashedBaseStyle" BasedOn="{StaticResource ButtonBaseStyle}" TargetType="Button">
     <Setter Property="Background" Value="Transparent"/>
     <Setter Property="Template">
         <Setter.Value>
             <ControlTemplate TargetType="Button">
                 <hc:DashedBorder BorderDashArray="3,2" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="Transparent" CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}">
                     <StackPanel Orientation="Horizontal" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}">
                         <Path x:Name="PathMain" Width="{TemplateBinding hc:IconElement.Width}" Height="{TemplateBinding hc:IconElement.Height}" Fill="{TemplateBinding Foreground}" SnapsToDevicePixels="True" Stretch="Uniform" Data="{TemplateBinding hc:IconElement.Geometry}"/>
                         <ContentPresenter x:Name="ContentPresenterMain" RecognizesAccessKey="True" VerticalAlignment="Center" Margin="6,0,0,0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                     </StackPanel>
                 </hc:DashedBorder>
                 <ControlTemplate.Triggers>
                     <Trigger Property="Content" Value="{x:Null}">
                         <Setter Property="Visibility" Value="Collapsed" TargetName="ContentPresenterMain"/>
                     </Trigger>
                     <Trigger Property="hc:IconElement.Geometry" Value="{x:Null}">
                         <Setter Property="Visibility" Value="Collapsed" TargetName="PathMain"/>
                         <Setter Property="Margin" Value="0" TargetName="ContentPresenterMain"/>
                     </Trigger>
                 </ControlTemplate.Triggers>
             </ControlTemplate>
         </Setter.Value>
     </Setter>
 </Style>

在这里插入图片描述

控件模板原型

我们想写一个控件模板,如果不是很熟练,我们就先把控件模板的原型写出来,这样更利于理解。

 <DockPanel>
     <!--这里仿照HandyControl,使用Gemotery。IconPacks怎么转Gemotery可以看我的文章-->


     <Border DockPanel.Dock="Top"
             Width="50"
             Height="50"
             CornerRadius="25"
             Background="DeepSkyBlue">
         <Path Data="{wpfEx:MaterialGeometry Kind=BellRing}"
               HorizontalAlignment="Stretch"
               VerticalAlignment="Stretch"
               SnapsToDevicePixels="True"
               Stretch="Uniform"
               Width="25"
               Height="25"
               Fill="White" />
     </Border>

     <TextBlock Text="TIM登录"
                HorizontalAlignment="Center" />
 </DockPanel>

在这里插入图片描述

控件模板

<Style x:Key="UserSelection"
       TargetType="RadioButton"
       BasedOn="{StaticResource {x:Type RadioButton}}">
    <Setter Property="Template">
        <Setter.Value>
            <!--先按照之前的样式粘贴一下-->
            <ControlTemplate TargetType="RadioButton">
                <DockPanel>
                    <Border DockPanel.Dock="Top"
                            Width="50"
                            Height="50"
                            CornerRadius="25"
                            Background="DeepSkyBlue">
                        <Path Data="{wpfEx:MaterialGeometry Kind=BellRing}"
                              HorizontalAlignment="Stretch"
                              VerticalAlignment="Stretch"
                              SnapsToDevicePixels="True"
                              Stretch="Uniform"
                              Width="25"
                              Height="25"
                              Fill="White" />
                    </Border>
                    <ContentPresenter x:Name="ContentPresenterMain"
                                      RecognizesAccessKey="True"
                                      VerticalAlignment="Center"
                                      Margin="6,0,0,0"
                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                </DockPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

在这里插入图片描述

然后里面能绑定的就绑定。也是照着HandyControl改的。注意这里的Banding用的是TemplateBinding

在这里插入图片描述

修改好的效果

<!--一个简单的FontSize修改-->
<Style x:Key="UserSelection"
       TargetType="RadioButton"
       BasedOn="{StaticResource {x:Type RadioButton}}">
    <Setter Property="Template">
        <Setter.Value>
            <!--先按照之前的样式粘贴一下-->
            <ControlTemplate TargetType="RadioButton">
                <DockPanel>
                    <Border DockPanel.Dock="Top"
                            Width="{TemplateBinding hc:IconElement.Width}"
                            Height="{TemplateBinding hc:IconElement.Height}"
                            CornerRadius="25"
                            Background="{TemplateBinding Foreground}">
                        <Path Data="{TemplateBinding hc:IconElement.Geometry}"
                              HorizontalAlignment="Stretch"
                              VerticalAlignment="Stretch"
                              SnapsToDevicePixels="True"
                              Stretch="Uniform"
                              Width="25"
                              Height="25"
                              Fill="{TemplateBinding Background}" />
                    </Border>
                    <ContentPresenter x:Name="ContentPresenterMain"
                                      RecognizesAccessKey="True"
                                      VerticalAlignment="Center"
                                        
                                      Margin="6,0,0,0"
                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                </DockPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

简单使用

<RadioButton Content="TIM登录"
             GroupName="UserSelect"
             Style="{StaticResource UserSelection}"
             Foreground="DeepSkyBlue"
             Background="White"
             hc:IconElement.Geometry="{wpfEx:MaterialGeometry Kind=AbTesting}" />

在这里插入图片描述

结论

HandyControl的源码看了真的是打开眼界,但是WPF的Xaml有一个无法在内部简单计算的问题。比如我想Witdh=Height = CornerRadius*2。我可能就要写个触发器了。我后面回去测试一下有没有方法可以在Xaml里面简单计算的。


http://www.niftyadmin.cn/n/5394544.html

相关文章

k8s二进制部署的搭建

1.1 常见k8s安装部署方式 ●Minikube Minikube是一个工具&#xff0c;可以在本地快速运行一个单节点微型K8S&#xff0c;仅用于学习、预览K8S的一些特性使用。 部署地址&#xff1a;Install Tools | Kubernetes ●Kubeadm Kubeadm也是一个工具&#xff0c;提供kubeadm init…

Openharmony - HDF平台驱动之I2C驱动和测试程序

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 概述I2C平台驱动I2C平台驱动HDF框架I2C平台驱动的使用I2C应用开发接口说明代码目录i2ctest.cBUILD.gnbundle.json修改config.json文件…

html中的meta 元信息

html中的meta 元信息 1. 配置字符编码 <meta charset"utf-8">2. 针对 IE 浏览器的兼容性配置。 <meta http-equiv"X-UA-Compatible" content"IEedge">3. 针对移动端的配置 <meta name"viewport" content"widt…

WPF 【十月的寒流】学习笔记(2):MVVM中是怎么实现通知的

文章目录 前言相关链接代码仓库项目配置代码初始代码ViewPersonViewModel 尝试老办法通知解决方案ObservableCollectionBindingListICollectionView 总结 前言 我们这次详细了解一下列表通知的底层是怎么实现的 相关链接 十月的寒流 MVVM实战技巧之&#xff1a;可被观测的集合…

Encoder和Decoder的详细介绍

——参考傅里叶变换&#xff08;Encoder&#xff09;、处理和傅里叶逆变换&#xff08;Decoder&#xff09; 1.Encoder&#xff08;编码器&#xff09; 编码器&#xff08;Encoder&#xff09;通常指的是在机器学习和神经网络领域中的一种组件或模型结构&#xff0c;用于将输入…

第四套CCF信息学奥赛c++ CSP-J认证初级组 中小学信奥赛入门组初赛考前模拟冲刺题(完善程序题)

第四套中小学信息学奥赛CSP-J考前冲刺题 三、完善程序题 第一题 田忌赛马 田忌赛马&#xff0c;田忌每赢一次齐王的马就得200金&#xff0c;,当然输了就扣200金币&#xff0c;平局则金币数 不变。 #include<iostream> using namespace std; int main(){int n;while(c…

dpdk协议栈之udp架构优化

dpdk优势 传统网络架构与 DPDK&#xff08;Data Plane Development Kit&#xff09;网络架构之间存在许多区别&#xff0c;而 DPDK 的优势主要体现在以下几个方面&#xff1a; 数据包处理性能&#xff1a;传统网络架构中&#xff0c;网络数据包的处理通常由操作系统的网络协议…

ui设计:利用即使设计设计出漂亮样式

目录 一、基本操作 二、具体介绍 6-1 填充图片 6-2 填充色 6-3 图标 右边栏基础设置 右边栏导出​编辑 一、基本操作 二、具体介绍 6-1 填充图片 选择其一图片填充 6-2 填充色 6-3 图标 右边栏基础设置 右边栏导出