最近在做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的,如下:



手动输入容易出错。只要生成为“资源”,下面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}"/>

wpf custom control的更多相关文章

  1. ClassLibary和WPF User Control LIbary和WPF Custom Control Libary的异同

    说来惭愧,接触WPF这么长时间了,今天在写自定义控件时遇到一个问题:运行界面中并没有显示自定义控件,经调试发现原来没有加载Themes中的Generic.xaml. 可是为什么在其他solution中 ...

  2. Recommended Practices for WPF Custom Control Developers

    I have always found that there isn’t enough documentation about Custom Control development in WPF. M ...

  3. [WPF] 将普通的Library工程,改造成WPF Custom Control 的Library

    1. 添加References PresentationCore PresentationFramework System.Xaml WindowsBase2. 修改AssemblyInfo.xsus ...

  4. Hosting custom WPF calendar control in AX 2012

    原作者: https://community.dynamics.com/ax/b/axilicious/archive/2013/05/20/hosting-custom-wpf-calendar-c ...

  5. Writing a Reusable Custom Control in WPF

    In my previous post, I have already defined how you can inherit from an existing control and define ...

  6. WPF中的Generic.xaml, theme以及custom control

    原文:WPF中的Generic.xaml, theme以及custom control 在Visual Studio中创建自定义控件时,所有控件都将添加到/Themes/Generic.xaml. 最 ...

  7. .NET Core学习笔记(2)—— WPF使用UWP Custom Control

    自.NET Core 3.0开始,某软加入了对WPF的支持.同时对XAML Islands也做了进一步加强.在.NET Core 3.0之前,我们只能在WPF程序中,通过两种方式有限制地使用Stand ...

  8. Tutorial: WPF User Control for AX2012

    原作者: https://community.dynamics.com/ax/b/goshoom/archive/2011/10/06/tutorial-wpf-user-control-for-ax ...

  9. WinForm中Component Class、User Control及Custom Control的区别和使用建议

    reference: http://blog.csdn.net/redstonehe/article/details/1536549 .NET Framework 为您提供了开发和实现新控件的能力.除 ...

随机推荐

  1. AJAX的简介

    AJAX 指异步JavaScript及XML(Asynchronous JavaScript And XML(异步JavaScript和XML)),是指一种创建交互式网页应用的网页开发技术. 国内通常 ...

  2. phalcon: dispatcher调度控制器

    phalcon: dispatcher调度控制器 我所理解的dispatcher调度控制器,实际上是对 router或者特定的url参数给与重组. 引用特定的类: //add use Phalcon\ ...

  3. html页面,左边点击链接,右边显示内容参考代码。

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  4. window2012 64bit 安装sqlserver2012 64bit调用excel的驱动安装

    如果电脑已经安装了32bit的office那么可以使用 管理员权限打开cmd,然会执行以下命令 AccessDatabaseEngine_X64.exe /passive

  5. linux笔记:搜索命令find,locate,which,whereis,grep

    命令名称:find功能:文件搜索命令所在路径:/bin/find用法:find 搜索范围 匹配条件其他:举例:find /root -name initfind /root -size +1024fi ...

  6. 索引器(C# 编程指南)

    原文地址:https://msdn.microsoft.com/zh-cn/library/6x16t2tx(VS.80).aspx 索引器允许类或结构的实例按照与数组相同的方式进行索引.索引器类似于 ...

  7. 8.3 ContosoMVCWeb官方案例学习

    1. 分页案例学习 2. 排序搜索案例学习 3.使用Configuration.cs中的Seed方法 在数据库迁移过程中,使用update-database,会运行seed方法.seed方法能够将初始 ...

  8. DOM事件流

    DOM事件标准定义了两种事件流:Capture(捕获)和Bubbing(冒泡):捕获和冒泡是javascript针对dom事件处理的先后顺序,所谓的先后顺序是指针对父标签与其嵌套子标签,如果父标签与嵌 ...

  9. [maven] settings 文件节点配置详解

    基本结构 <settings xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3. ...

  10. 《javascript高级程序设计》 第20章 JSON

    20.1 语法 20.1.1 简单值 20.1.2 对象 20.1.3 数组 20.2 解析与序列化 20.2.1 JSON 对象 20.2.2 序列化选项 20.2.3 解析选项 JSON 对象有两 ...