zoukankan      html  css  js  c++  java
  • wpf custom control

    最近在做WPF,记录一下自定义控件的制作过程,源码请点击:源码

    1、目标

    实现一个如图所示的可增减的数字框:
    数字框

    2、先画Template

    可以在Generic.xaml中画,也可以用MergedDictionary连接到其他xaml中。

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/CustomControls;component/Themes/UpDownNumeric.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    

    3、再实现UpDownNumeric

    基类选择Control,也可以根据目标就近选择基类(比如ItemsControl、HeaderedContentControl之类的)。想好要暴露哪些属性、事件和命令,比如在这个例子里,只要暴露1个ValueProperty、2个CommandProperty(只贴增的,减类似不重复贴了)、和1个ValueChanged事件即可。

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(int), typeof(UpDownNumeric),
        new PropertyMetadata(new PropertyChangedCallback(OnValueChanged)));
    
    public static readonly DependencyProperty UpCommandProperty =
        DependencyProperty.Register("UpCommand", typeof(ICommand), typeof(UpDownNumeric));
    
    public static readonly RoutedEvent ValueChangedEvent =
        EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble,
        typeof(RoutedPropertyChangedEventHandler<int>), typeof(UpDownNumeric));
    

    再把这些属性包装成我们熟悉的.net的属性和事件,基于DelegateCommand实现命令、和触发ValueChanged的事件即可。

    4、坑1:如果逻辑里的属性与控件的属性类型不匹配,要实现相应的IValueConverter

    在这个例子里, 我把int型的Value绑定到TextBox的Text,int到string不能直接绑定,因此要实现一个Int2StringConverter,并在绑定时指定。否则不会显示值。

    <TextBox Text="{TemplateBinding Value, Converter={StaticResource Int2StringConverter}}"/>
    

    5、坑2:Image.Source的Pack Uri路径

    这个路径如果没写对,要么编译不通过,要么虽然编译成功但运行的时候显示不出来。这里有几点关键:

    5.1、右键图片->属性->生成操作->务必选择“资源”(Resource)

    请不要选择“内容”或“嵌入的资源”,也不要将图片添加到“项目资源”中。“复制到输出目录”选择“不复制”。我分别尝试了这几种生成方式,如下:
    资源:生成到.g.resources
    资源
    内容:不生成到dll里
    内容
    嵌入的资源:生成到Resources文件夹中,与
    .g.resources同级
    嵌入的资源
    项目资源:生成到*.Properties.Resources.resources
    项目资源

    5.2、Pack Uri路径

    网上到处是copy来的一大堆理论,看的晕。我试下来,在vs的Image.Source属性窗口里选,由vs自动生成的路径总是OK的,如下:
    vs
    手动输入容易出错。只要生成为“资源”,下面3种写法都是正确的。
    绝对路径:pack:///application:,,,/CustomControls;component/Resources/up.png
    绝对路径-缩写版:/CustomControls;component/Resources/up.png
    相对路径:../Resources/up.png

    6、坑3:Template与控件Logic务必分离

    这里的分离是指:Logic不应知道具体的控件名,Logic只暴露依赖属性(包括属性+命令),Template负责绑定属性。这种分离的好处是:如果用户不喜欢你的Template,自己再定制一个,只需绑定到同样的属性+命令,即可实现控件的行为。否则用户就无法改写Template了。

    6.1、错误的实现方式
    private Button upBtn;
    public override void OnApplyTemplate(){
      upBtn = (Button)this.Template.FindName("btnUp", this);
      upBtn.Click = btn_Click;
    }
    

    这样写,就把Logic和Template绑死了。

    6.2、正确的实现方式
    //后台定义UpCommandProperty,实现为DelegateCommand或RoutedCommand,前台Template去绑定
    public static readonly DependencyProperty UpCommandProperty =
      DependencyProperty.Register("UpCommand", typeof(ICommand), typeof(UpDownNumeric));
    
    <Button Command="{TemplateBinding UpCommand}"/>
    
  • 相关阅读:
    【Spark 深入学习 02】- 我是一个凶残的spark
    【Spark 深入学习 01】 Spark是什么鬼?
    【Big Data
    【Netty】通俗地讲,Netty 能做什么?
    【Jetty】Jetty 的工作原理以及与 Tomcat 的比较
    【Tomcat】Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析
    【Tomcat】Tomcat 系统架构与设计模式,第 1 部分: 工作原理
    【Tomcat】Servlet 工作原理解析
    【Tomcat】面向初级 Web 开发人员的 Tomcat
    【Big Data
  • 原文地址:https://www.cnblogs.com/AlexanderYao/p/4711019.html
Copyright © 2011-2022 走看看