WPF自定义控件的三种方式
简介: 某些场景下,我们确实需要创建新的控件。此时,理解 WPF不同控件的创建方法就显得非常重要。 WPF 提供3个用于创建控件的方法,每个方法都提供不同的灵活度。
WPF控件可以通过数据模型(DataTemplate)、样式(Style)、控件模板(ControlTemplate)和触发器(Trigger)等机制减少创建新控件的需要。 但是,某些场景下,我们确实需要创建新的控件。此时,理解 WPF不同控件的创建方法就显得非常重要。 WPF 提供3个用于创建控件的方法,每个方法都提供不同的灵活度,下面分别进行介绍。
1 基于UserControl 创建
创建控件最简单一个方法就是基于UserControl 类进行继承。此时,我们可以将WPF中现有组件添加到 UserControl 画布上来,并将各组件进行命名,这样可以在后台进行组件访问和使用事件处理程序。 UserControl 可以利用丰富内容、样式和触发器的优点。 但是,继承自 UserControl的控件,将无法使用 DataTemplate 或 ControlTemplate 来自定义UI外观。
2 基于Control 创建
基于Control类创建自定义控件的方法 ,可以使用模板定义UI外观。而且可以将后台逻辑和前端样式展现上进行分离。 另外,这种方法创建的自定义控件,还支持使用命令和绑定来完成相关动作,实现类似事件的效果。最后,控件可以重新定义ControlTemplate和DataTemplate来自定义UI外观。控件支持不同的主题。
3 基于 FrameworkElement 创建
一般来说,基于 UserControl 或 Control 创建的自定义控件即可完成业务需求,但是,在一些特殊情况下,简单的元素组合不能满足自定义控件的UI外观要求。此时,基于FrameworkElement 创建自定义控件是一个很好的选择。
基于FrameworkElement创建控件,一方面可以通过重写的 OnRender 方法进行UI的直接绘制。 另一方面,可以通过自定义元素组合来可视化编写组件的外观。
4 依赖属性
WPF 可以通过设置控件的属性来更改其外观和行为。其中的依赖属性可以让自定义控件执行以下操作:
- 在样式中设置该属性。
- 将该属性绑定到数据源。
- 使用动态资源作为该属性的值。
- 对该属性进行动画处理。
如果控件的属性支持以上任一功能,应将该属性实现为依赖属性。 下面给出一个微软官方文档的示例程序:
/// <summary>
/// Identifies the Value dependency property.
/// </summary>
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value", typeof(decimal), typeof(NumericUpDown),
new FrameworkPropertyMetadata(MinValue, new PropertyChangedCallback(OnValueChanged),
new CoerceValueCallback(CoerceValue))); /// <summary>
/// Gets or sets the value assigned to the control.
/// </summary>
public decimal Value
{
get { return (decimal)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
} private static object CoerceValue(DependencyObject element, object value)
{
decimal newValue = (decimal)value;
NumericUpDown control = (NumericUpDown)element; newValue = Math.Max(MinValue, Math.Min(MaxValue, newValue)); return newValue;
} private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
NumericUpDown control = (NumericUpDown)obj; RoutedPropertyChangedEventArgs<decimal> e = new RoutedPropertyChangedEventArgs<decimal>(
(decimal)args.OldValue, (decimal)args.NewValue, ValueChangedEvent);
control.OnValueChanged(e);
}
此示例代码来自官网控件创作概述 - WPF .NET Framework | Microsoft Docs ,其中定义一个名为 ValueProperty的依赖属性(DependencyProperty ),通过调用DependencyProperty.Register向属性系统注册属性名称Value,其中包含了三个核心信息:
- 属性的名称Value
- 属性的类型decimal
- 拥有属性的类型NumericUpDown
- 属性元数据信息(FrameworkPropertyMetadata)
其中,属性的元数据包含属性的默认值, CoerceValueCallback 和 PropertyChangedCallback 。 CoerceValue 确保 Value 大于或等于 MinValue 且小于或等于 MaxValue。另外,PropertyChangedCallback 回调方法为 OnValueChanged ,来处理属性值变化的相关逻辑,后面通过RoutedPropertyChangedEventArgs创建了一个路由事件,并通过control.OnValueChanged(e)来进行触发。
原文链接
本文为阿里云原创内容,未经允许不得转载。
WPF自定义控件的三种方式的更多相关文章
- wpf 创建动画三种方式
动画类型 : 故事版,CompositionTarget,DispachTime 那么到此,三种动态创建动画的方法都已经详细介绍过了,大家可能会有种感觉,比较钟情于第一种WPF/Silverlight ...
- WPF自定义控件的两种方式
方法A: 第一步:My自定义控件:Control 第二步:针对 “My自定义控件” 类型,编写<style>或<模板>(UI的外观完全由用户自己定义) 第三步: 使用My自定 ...
- WPFの三种方式实现快捷键
最近,对wpf添加快捷键的方式进行了整理.主要用到的三种方式如下: 一.wpf命令: 资源中添加命令 <Window.Resources> <RoutedUICommand x:Ke ...
- WPF中实现PropertyGrid(用于展示对象的详细信息)的三种方式
原文:WPF中实现PropertyGrid(用于展示对象的详细信息)的三种方式 由于WPF中没有提供PropertyGrid控件,有些业务需要此类的控件.这篇文章介绍在WPF中实现PropertyGr ...
- 监视EntityFramework中的sql流转你需要知道的三种方式Log,SqlServerProfile, EFProfile
大家在学习entityframework的时候,都知道那linq写的叫一个爽,再也不用区分不同RDMS的sql版本差异了,但是呢,高效率带来了差灵活性,我们 无法控制sql的生成策略,所以必须不要让自 ...
- iOS字体加载三种方式
静态加载 动态加载 动态下载苹果提供的多种字体 其他 打印出当前所有可用的字体 检查某字体是否已经下载 这是一篇很简短的文章,介绍了 iOS 自定义字体加载的三种方式. 静态加载 这个可以说是最简单最 ...
- 0036 Java学习笔记-多线程-创建线程的三种方式
创建线程 创建线程的三种方式: 继承java.lang.Thread 实现java.lang.Runnable接口 实现java.util.concurrent.Callable接口 所有的线程对象都 ...
- 【整理】Linux下中文检索引擎coreseek4安装,以及PHP使用sphinx的三种方式(sphinxapi,sphinx的php扩展,SphinxSe作为mysql存储引擎)
一,软件准备 coreseek4.1 (包含coreseek测试版和mmseg最新版本,以及测试数据包[内置中文分词与搜索.单字切分.mysql数据源.python数据源.RT实时索引等测 ...
- JDBC的批处理操作三种方式 pstmt.addBatch()
package lavasoft.jdbctest; import lavasoft.common.DBToolkit; import java.sql.Connection; import java ...
- 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】
一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...
随机推荐
- 【Unity 3D游戏开发】在Unity使用NoSQL数据库方法介绍
随着游戏体积和功能的不断叠加,游戏中的数据也变得越来越庞杂,这其中既包括玩家产生的游戏存档等数据,例如关卡数.金币等,也包括游戏配置数据,例如每一关的配置情况.尽管Unity提供了PlayerPref ...
- docker相关命令杂理
- 2020.11.16docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] #保存现有的镜像 # docker commit -a "r ...
- vue三种插槽
1. 作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件 . 2. 分类:默认插槽.具名插槽.作用域插槽 3. 使用方式: a.默认插 ...
- markdown 常用表情符号 (github emoji)
markdown 常用表情(emoji) 官网[非笔者维护,仅做引用] Face Smiling 咧嘴笑 grinning 汗颜笑 sweat_smile 爆笑 rofl 眨眼笑 wink innoc ...
- Python爬取腾讯视频电影名称和链接(一)
1 import requests 2 import json 3 from bs4 import BeautifulSoup #网页解析获取数据 4 import sys 5 import re 6 ...
- 《写给程序员的Python教程》阅读随笔---python禅学(Zen_of_python)
Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Comp ...
- MySQL字符集和语言
字符集和校对顺序 数据库表被用来存储和检索数据.不同的语言和字符集需要以不同的方式存储和检索.因此,MySQL需要适应不同的字符集(不同的字母和字符),适应不同的排序和检索数据的方法. 在讨论多种 ...
- #斜率优化,二分#CF631E Product Sum
题目 有一个数列 \(a\),其权值为 \(\sum_{i=1}^ni*a_i\), 现在可以任意选择其中一个数字扔到任意位置,使权值和最大. \(n\leq 2*10^5,|a_i|\leq 10^ ...
- 浅谈OpenHarmony LiteOS-A内核之基础硬件——中断控制器GIC400
一.前言 OpenAtom OpenHarmony(以下简称"OpenHarmony")采用多内核架构,支持Linux内核的标准系统.LiteOS-A的小型系统.LiteOS-M的 ...
- OpenHarmony Camera源码分析
一.简介 当前,开源在科技进步和产业发展中发挥着越来越重要的作用,OpenAtom OpenHarmony(简称"OpenHarmony")赋予了开发者孕育创新的种子,也为数字化产 ...