[UWP 自定义控件]了解模板化控件(5.1):TemplatePart vs. VisualState

在前两篇文章中,我们分别使用了templatepart和visualstate的方法实现了相同的功能,其中visualstate显然更具灵活性。在这种情况下,我通常更倾向于使用visualstate。然而,在实际应用中,这两种实现方式并不是互斥的,许多模板化控件会同时使用这两种方法。

使用VisualState的好处包括:

代码和UI分离,使得控件扩展更灵活。可以使用Blend轻松实现动画。

尽管VisualState有诸多优势,但并不是说所有功能都必须使用VisualState实现。以下情况我会选择使用TemplatePart:

需要快速实现一个控件。某个行为是固定的,不需要扩展。需要在代码中操作UI,例如Slider或ComboBox。为了强调某个部件是控件必需的。为了隐藏实现细节,限制派生类或ControlTemplate修改重要的逻辑。

其中,使用TemplatePart产生的扩展性问题是我谨慎使用这种方案的最大因素。

除了VisualState,TemplatePart的功能也常常会被TemplateBinding所替代。前面的例子展示了使用VisualState在UI上的优势,这次我们用另一个控件DateTimeSelector来讨论使用TemplatePart在扩展性上的其他问题。

使用TemplatePart

DateTimeSelector组合了CalendarDatePicker和TimePicker,用于选择日期和时间(SelectedDateTime)。其XAML如下:

                                                                                

相应的代码如下:

[TemplatePart(Name = DateElementPartName, Type = typeof(CalendarDatePicker))][TemplatePart(Name = TimeElementPartName, Type = typeof(TimePicker))]public class DateTimeSelector : Control{    public const string DateElementPartName = "DateElement";    public const string TimeElementPartName = "TimeElement";    public static readonly DependencyProperty SelectedDateTimeProperty =        DependencyProperty.Register("SelectedDateTime", typeof(DateTime), typeof(DateTimeSelector), new PropertyMetadata(DateTime.Now, OnSelectedDateTimeChanged));    private static void OnSelectedDateTimeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)    {        DateTimeSelector target = obj as DateTimeSelector;        DateTime oldValue = (DateTime)args.OldValue;        DateTime newValue = (DateTime)args.NewValue;        if (oldValue != newValue)            target.OnSelectedDateTimeChanged(oldValue, newValue);    }    public DateTimeSelector()    {        this.DefaultStyleKey = typeof(DateTimeSelector);    }    public DateTime SelectedDateTime    {        get { return (DateTime)GetValue(SelectedDateTimeProperty); }        set { SetValue(SelectedDateTimeProperty, value); }    }    private CalendarDatePicker _dateElement;    private TimePicker _timeElement;    private bool _isUpdatingDateTime;    protected override void OnApplyTemplate()    {        base.OnApplyTemplate();        if (_dateElement != null)            _dateElement.DateChanged -= OnDateElementDateChanged;        _dateElement = GetTemplateChild(DateElementPartName) as CalendarDatePicker;        if (_dateElement != null)            _dateElement.DateChanged += OnDateElementDateChanged;        if (_timeElement != null)            _timeElement.TimeChanged -= OnTimeElementTimeChanged;        _timeElement = GetTemplateChild(TimeElementPartName) as TimePicker;        if (_timeElement != null)            _timeElement.TimeChanged += OnTimeElementTimeChanged;        UpdateElement();    }    protected virtual void OnSelectedDateTimeChanged(DateTime oldValue, DateTime newValue)    {        UpdateElement();    }    private void OnDateElementDateChanged(CalendarDatePicker sender, CalendarDatePickerDateChangedEventArgs args)    {        UpdateSelectDateTime();    }    private void OnTimeElementTimeChanged(object sender, TimePickerValueChangedEventArgs e)    {        UpdateSelectDateTime();    }    private void UpdateElement()    {        _isUpdatingDateTime = true;        try        {            if (_dateElement != null)                _dateElement.Date = SelectedDateTime.Date;            if (_timeElement != null)                _timeElement.Time = SelectedDateTime.TimeOfDay;        }        finally        {            _isUpdatingDateTime = false;        }    }    private void UpdateSelectDateTime()    {        if (_isUpdatingDateTime)            return;        DateTime dateTime = DateTime.Now;        if (_dateElement != null && _dateElement.Date.HasValue)            dateTime = _dateElement.Date.Value.Date;        if (_timeElement != null)            dateTime = dateTime.Add(_timeElement.Time);        SelectedDateTime = dateTime;    }}

可以看出,DateTimeSelector通过监视CalendarDatePicker的DateChanged和TimePicker的TimeChanged来改变SelectedDateTime的值。

DateTimeSelector的代码非常简单,控件也运行良好,但如果某天需要将CalendarDatePicker替换为DatePicker或某个第三方的日期选择控件,DateTimeSelector就无能为力了,既不能通过修改ControlTemplate,也不能通过继承来达到目的。

使用TemplateBinding

通常在构建这类控件时,应先考虑其数据和行为,而不关心其UI。DateTimeSelector最核心的功能是通过选择Date和Time得出组合起来的DateTime,那么就可以先写出如下的类:

public class DateTimeSelector2 : Control{    public static readonly DependencyProperty DateProperty =        DependencyProperty.Register("Date", typeof(DateTime), typeof(DateTimeSelector2), new PropertyMetadata(DateTime.Now, OnDateChanged));    private static void OnDateChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)    {        DateTimeSelector2 target = obj as DateTimeSelector2;        DateTime oldValue = (DateTime)args.OldValue;        DateTime newValue = (DateTime)args.NewValue;        if (oldValue != newValue)            target.OnDateChanged(oldValue, newValue);    }    public static readonly DependencyProperty TimeProperty =        DependencyProperty.Register("Time", typeof(TimeSpan), typeof(DateTimeSelector2), new PropertyMetadata(TimeSpan.Zero, OnTimeChanged));    private static void OnTimeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)    {        DateTimeSelector2 target = obj as DateTimeSelector2;        TimeSpan oldValue = (TimeSpan)args.OldValue;        TimeSpan newValue = (TimeSpan)args.NewValue;        if (oldValue != newValue)            target.OnTimeChanged(oldValue, newValue);    }    public static readonly DependencyProperty DateTimeProperty =        DependencyProperty.Register("DateTime", typeof(DateTime), typeof(DateTimeSelector2), new PropertyMetadata(DateTime.Now, OnDateTimeChanged));    private static void OnDateTimeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)    {        DateTimeSelector2 target = obj as DateTimeSelector2;        DateTime oldValue = (DateTime)args.OldValue;        DateTime newValue = (DateTime)args.NewValue;        if (oldValue != newValue)            target.OnDateTimeChanged(oldValue, newValue);    }    public DateTimeSelector2()    {        this.DefaultStyleKey = typeof(DateTimeSelector2);    }    public DateTime Date    {        get { return (DateTime)GetValue(DateProperty); }        set { SetValue(DateProperty, value); }    }    public TimeSpan Time    {        get { return (TimeSpan)GetValue(TimeProperty); }        set { SetValue(TimeProperty, value); }    }    public DateTime DateTime    {        get { return (DateTime)GetValue(DateTimeProperty); }        set { SetValue(DateTimeProperty, value); }    }    private bool _isUpdatingDateTime;    protected virtual void OnDateChanged(DateTime oldValue, DateTime newValue)    {        UpdateDateTime();    }    protected virtual void OnTimeChanged(TimeSpan oldValue, TimeSpan newValue)    {        UpdateDateTime();    }    protected virtual void OnDateTimeChanged(DateTime oldValue, DateTime newValue)    {        _isUpdatingDateTime = true;        try        {            Date = newValue.Date;            Time = newValue.TimeOfDay;        }        finally        {            _isUpdatingDateTime = false;        }    }    private void UpdateDateTime()    {        if (_isUpdatingDateTime)            return;        DateTime = Date.Date.Add(Time);    }}

控件的代码并不清楚ControlTemplate中包含什么控件,它只关心自己的数据。

在XAML中通过绑定使用这些数据。

                                                                                                                                                                

[UWP 自定义控件]了解模板化控件(5.1):TemplatePart vs. VisualState

这里给出了两个Style,分别使用了CalendarDatePicker和DatePicker,通过TwoWay Binding访问DateTimeSelector2中的Date属性。如果你的TemplatedControl需要有良好的扩展能力,可以尝试使用这种方式。

以上就是[UWP 自定义控件]了解模板化控件(5.1):TemplatePart vs. VisualState的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/191949.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月1日 13:32:01
下一篇 2025年11月1日 13:32:33

相关推荐

  • 数字黄金PK数字现金:比特币与比特币现金全面解析

    随着加密货币的发展,比特币(BTC)和比特币现金(BCH)成为市场关注的两大数字货币,前者被誉为“数字黄金”,后者则强调交易支付的便利性,被称为“数字现金”。本文将全面解析两者的区别及获取方式。 一、比特币(BTC)与比特币现金(BCH)概览 比特币(BTC)诞生于2009年,以去中心化、总量有限(…

    2025年12月11日
    000
  • Griffin AI(GAIN)币是什么?怎么样?GAIN代币经济与空投领取

    目录 GriffinAI(GAIN)最新动态GriffinAI是什么GriffinAI技术架构GAIN币是什么GAIN代币经济学常见问题 griffin ai 是一个将人工智能与 defi 自动化相结合的去中心化平台。其核心产品 agent builder 允许用户无需编写代码即可创建、定制和部署 …

    2025年12月11日
    000
  • 新手如何获取免费加密货币?五种最佳赚取方式详解

    想免费获取加密货币?对于新手而言,参与空投、测试网任务、质押奖励与社区活动是较为安全且成本低的入门路径。本文将介绍五种常见且高效的方式,并在步骤中提供实际操作要点与风险提示,帮助快速上手并避免常见陷阱。 五种免费获取加密货币的方式概览 1. 项目空投(Airdrop):许多项目通过快照历史持仓或完成…

    2025年12月11日
    000
  • 欧易交易所app下载:苹果手机/安卓手机下载okx官方APP教程

    欧易交易所(OKX)是一款全球领先的数字资产交易平台,致力于为用户提供安全、便捷、专业的数字货币交易服务。平台支持多种主流数字货币的交易,包括比特币(BTC)、以太坊(ETH)等,并提供币币交易、合约交易、杠杆交易等多种交易方式。 下载欧易APP 1、针对苹果手机用户:       直接点击提供的官…

    2025年12月11日
    000
  • DOGE,XRP现货ETF正式上市,当前各类加密ETF进展如何?一文剖析

    DOGE和XRP现货ETF的正式上市无疑是行业焦点。这一事件不仅标志着主流%ignore_a_1%市场对数字资产认可度的提升,也预示着更多传统投资者将有机会以更便捷、合规的方式参与到加密资产的投资中。然而,DOGE和XRP并非唯一的参与者,全球范围内各类加密ETF的进展如火如荼,从比特币现货ETF的…

    2025年12月11日
    000
  • 五大稳定币链全面解析:发展策略、社群、开发进度与核心数据

    随着加密市场发展,稳定币已成为数字货币生态中不可或缺的组成部分。本文将从发展策略、社群活跃度、开发进度以及核心数据四个维度,全面解析当前市场五大主流稳定币链。 一、USDT(泰达币) 发展策略:以市场占有率最大为目标,提供美元挂钩的稳定币服务,兼顾合规性与全球流通性。 社群:全球用户广泛,交易量高,…

    2025年12月11日
    000
  • 以太坊(ETH)一周暴跌超20%,原因何在?

    过去一周,以太坊(ETH)价格累计下跌超过20%,引发市场广泛关注。投资者纷纷讨论其暴跌背后的主要原因及未来走势可能性。 一、市场情绪与宏观因素 宏观经济数据疲软:近期美国通胀数据及就业数据表现超预期,导致加密市场资金面紧张,ETH受抛压明显增加。 投资者风险偏好下降:在股市波动加剧的背景下,部分资…

    2025年12月11日
    000
  • 加密货币做空是什么意思?做空赚钱原理与风险全解析

    在加密货币市场中,许多投资者会关注不仅仅是价格上涨的机会,也会参与做空交易来获取收益。所谓做空,是指投资者押注币价下跌,从价格下跌中获利的一种操作方式。 一、加密货币做空的基本原理 做空交易通常通过借入加密货币卖出,期望在未来以更低价格回购归还,从中赚取差价。例如,如果投资者认为比特币价格将下跌,可…

    2025年12月11日
    000
  • 币安binance交易所官网安全访问入口 币安最新版v3.3.5官方APP下载

    币安binance是全球领先的数字货币交易平台,提供了官网访问入口与官方app下载两种便捷方式,方便用户随时随地进行账户管理与资产交易。下面为大家详细整理了访问与安装的流程。 币安Binance官网安全访问入口 ① 打开浏览器,输入币安官网地址并进入首页。② 点击右上角注册/登录按钮。③ 输入手机号…

    2025年12月11日 好文分享
    000
  • 币安biance交易所 v3.2.5 官方安卓最新版下载入口

    Binance币安 欧易OKX ️ Huobi火币️ 币安(Binance)是全球用户量领先的加密货币交易平台之一,其官方安卓App持续更新以提供更稳定、安全的交易体验。当前应用市场中的最新版本已远超v3.2.5,建议用户下载最新版以获得完整功能与安全保障。 确认官方正版渠道 为避免下载到仿冒或篡改…

    2025年12月11日
    000
  • 火币HUOBI官方网站安全访问入口

    对于很多新手用户来说,想要进入加密货币市场,选择一个安全可靠的交易平台是第一步。火币huobi(现htx)作为全球知名的虚拟货币交易平台之一,为用户提供了稳定的交易环境与全面的服务。本文将为大家介绍火币官方网站入口、htx客户端app下载方式以及注册与账户开通流程。 一、火币HUOBI官网安全访问入…

    2025年12月11日
    000
  • 2025欧意交易所app官方下载 欧意 v6.138.1 最新版app安卓版

    欧意交易所App是一款广受欢迎的数字资产交易平台,致力于为全球用户提供安全、便捷、专业的加密货币交易服务。平台支持多种主流数字货币的交易,界面友好,功能强大,是您管理和增值数字资产的理想选择。 欧易官网入口: 欧易官网直链下载: 下载步骤 1、点击上方提供的官方下载链接,浏览器将自动开始下载欧意交易…

    2025年12月11日
    000
  • ouyi官方网站安全访问入口 欧易OKX手机端App下载+账户注册指南

    欧易okx是全球知名的数字货币交易平台,提供全面的交易服务与便捷的移动端体验。本文将详细介绍欧易官方网站安全访问入口、手机端app下载及账户注册流程,帮助新手用户快速上手。 欧易官方网站安全访问入口 ① 打开浏览器,输入欧易OKX官网地址并访问首页。② 点击右上角的注册/登录按钮。③ 填写手机号或邮…

    2025年12月11日 好文分享
    000
  • 火币htx交易所官网下载地址 火币(HTX)交易所 v11.3.0官方安卓版下载

    Binance币安 欧易OKX ️ Huobi火币️ 火币HTX交易所的官方下载渠道是确保账户和资金安全的第一步。直接访问其官网获取最新版本的应用,能有效避免因使用非官方渠道下载的APP而带来的风险,比如信息泄露或钓鱼攻击。 官方网站与下载方式 火币HTX的官网地址为: https://www.ht…

    2025年12月11日
    000
  • 欧易OKE官方网站安全入口 欧易交易所官方APP下载链接

    欧易oke是全球领先的数字货币交易平台,提供便捷、安全的交易服务和丰富的币种选择。本文将详细介绍欧易oke官方网站安全入口以及官方app下载链接,帮助新手用户快速注册和开始交易。 欧易OKE官方网站安全入口: ① 打开浏览器,访问欧易OKE官网。② 点击右上角的注册/登录按钮。③ 输入手机号或邮箱、…

    2025年12月11日 好文分享
    000
  • 以太坊价格延续跌势,市场担忧情绪加剧

    近期,以太坊(ETH)价格延续下跌趋势,市场情绪明显趋于谨慎。投资者对短期行情波动和宏观因素影响表示担忧,市场成交量有所下降。 一、以太坊价格表现及市场情绪 ETH价格近期持续下探,短线跌幅超过5%。交易深度显示卖盘压力增加,市场投资者情绪偏向保守。 二、如何购买以太坊ETH 为了方便投资者快速参与…

    2025年12月11日
    000
  • Alpha上线Hana Network(HANA)交易,支持多种交易对

    近期,Alpha平台上线了Hana Network(HANA)交易,支持多种交易对,为投资者提供更多交易选择。市场对该代币的关注度有所提升,交易活跃度上升。 一、HANA代币及交易概况 Hana Network(HANA)是一种新兴区块链资产,Alpha平台上线后支持包括HANA/USDT、HANA…

    2025年12月11日
    000
  • 什么是跨链桥?市面上有哪些跨链桥?一文介绍

    目录 什么是跨链桥?跨链桥如何提升DeFi交易效率?市面上有哪些跨链桥?OKX 桥币安桥仲裁桥Celer cBridge轨道金融突触桥传送门令牌桥(原虫洞)雪崩桥跨桥如何评估跨链桥的安全性安全审计智能合约安全历史表现和事件响应Oracle 集成和数据验证去中心化和信任最小化社区和开发者参与跨链桥面临…

    2025年12月11日
    000
  • Scilex控股公司宣布向Datavault AI投资1.5亿美元比特币

    近日,Scilex控股公司宣布将向Datavault AI投资1.5亿美元比特币,进一步加码加密资产布局,凸显企业对数字货币市场的信心。 一、投资概况 此次投资主要用于Datavault AI生态建设及比特币持仓扩张。企业囤币潮正在持续,机构参与度提升,市场关注比特币的中长期价格走势。 二、如何购买…

    2025年12月11日
    000
  • 三个地址场外购入60,333枚ETH,浮亏超1600万美元

    近日,市场消息显示,三个地址在场外购入60,333枚以太坊(ETH),当前浮亏已超过1600万美元,反映出加密市场波动风险仍然较高。 一、交易概况 此次场外购入主要集中于大额投资者,旨在加大以太坊持仓。然而短期市场波动带来浮亏压力,投资者需关注价格变动及潜在风险。 二、如何参与以太坊交易 为了方便投…

    2025年12月11日
    000

发表回复

登录后才能评论
关注微信