当前位置: 首页 > article >正文

WPF自定义控件实战:从用户吐槽到优雅实现——我的DateTimePicker开发踩坑记

WPF自定义控件实战从用户吐槽到优雅实现——我的DateTimePicker开发踩坑记那天产品经理拍着桌子说我们的用户需要精确到秒的时间选择我看了看系统里那个老旧的DatePicker只能显示年月日心里默默叹了口气。这就是我踏上WPF自定义DateTimePicker控件开发之旅的起点。1. 为什么需要自定义DateTimePicker市面上主流的WPF日期选择控件比如MaterialDesign和HandyControl提供的解决方案大多只支持到日期级别。当业务场景需要精确到时分秒时开发者通常面临几个选择组合使用多个控件DatePicker TimePicker寻找第三方库自己动手实现组合控件的方式看似简单但会带来一系列问题!-- 典型的组合方案 -- StackPanel OrientationHorizontal DatePicker SelectedDate{Binding SelectedDate}/ TimePicker SelectedTime{Binding SelectedTime}/ /StackPanel这种方案的问题在于数据绑定需要处理两个独立属性UI风格难以统一占用更多屏幕空间用户体验不连贯2. 技术选型与架构设计2.1 基础控件选择经过评估我决定基于WPF的Calendar控件进行扩展主要考虑因素包括方案优点缺点继承Calendar直接获得日期选择功能需要完全重写时间选择部分组合现有控件开发速度快样式统一困难从头实现完全可控开发成本高最终选择继承Control类内嵌Calendar控件作为日期选择部分这样既能保持灵活性又能复用现有功能。2.2 核心数据结构时间数据的管理是关键我设计了以下依赖属性public static readonly DependencyProperty SelectedDateTimeProperty DependencyProperty.Register( SelectedDateTime, typeof(DateTime?), typeof(DateTimePicker), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedDateTimeChanged)); private static void OnSelectedDateTimeChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { // 处理时间变化逻辑 }3. 实现过程中的五大坑点3.1 Popup的焦点管理当用户点击下拉按钮时Popup应该显示点击外部时应该关闭。这看似简单实则暗藏玄机// 错误的实现方式 popup.StaysOpen false; // 正确的焦点管理 protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) { if (!popup.IsKeyboardFocusWithin !toggleButton.IsKeyboardFocusWithin) { popup.IsOpen false; } base.OnLostKeyboardFocus(e); }3.2 时间数据的绑定与转换时间部分需要处理24小时制、分钟和秒的选择。我采用了三个ListBox分别显示时、分、秒ListBox x:NameHourList ItemsSource{Binding Hours} SelectedItem{Binding SelectedHour}/ ListBox x:NameMinuteList ItemsSource{Binding Minutes} SelectedItem{Binding SelectedMinute}/ ListBox x:NameSecondList ItemsSource{Binding Seconds} SelectedItem{Binding SelectedSecond}/数据源的初始化public IEnumerableint Hours Enumerable.Range(0, 24); public IEnumerableint Minutes Enumerable.Range(0, 60); public IEnumerableint Seconds Enumerable.Range(0, 60);3.3 UI样式的自适应为了让控件在不同DPI和窗口大小下都能良好显示我使用了ViewBox和自适应布局Style TargetType{x:Type local:DateTimePicker} Setter PropertyTemplate Setter.Value ControlTemplate TargetType{x:Type local:DateTimePicker} Viewbox StretchUniform !-- 控件内容 -- /Viewbox /ControlTemplate /Setter.Value /Setter /Style3.4 键盘导航支持好的控件应该支持完整的键盘操作Tab键在控件各部分间切换焦点方向键选择时间Enter键确认选择实现代码示例protected override void OnKeyDown(KeyEventArgs e) { switch (e.Key) { case Key.Up: // 处理上箭头选择 break; case Key.Down: // 处理下箭头选择 break; case Key.Enter: ConfirmSelection(); break; } base.OnKeyDown(e); }3.5 国际化支持为了让控件支持多语言环境需要考虑日期时间格式本地化日历显示如伊斯兰历、农历文本资源的外部化解决方案是使用CultureInfo和资源字典public CultureInfo CurrentCulture { get { return (CultureInfo)GetValue(CurrentCultureProperty); } set { SetValue(CurrentCultureProperty, value); } }4. 封装与团队共享4.1 创建NuGet包将控件打包成NuGet包可以方便团队使用创建新的类库项目配置.nuspec文件添加依赖项打包发布nuget pack MyDateTimePicker.nuspec -OutputDirectory .\artifacts4.2 样式资源字典对于不想使用NuGet的团队可以提供样式资源字典ResourceDictionary xmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentation xmlns:xhttp://schemas.microsoft.com/winfx/2006/xaml xmlns:localclr-namespace:MyDateTimePicker.Controls Style TargetType{x:Type local:DateTimePicker} BasedOn{StaticResource {x:Type local:DateTimePicker}} !-- 自定义样式 -- /Style /ResourceDictionary5. 性能优化技巧在开发过程中我发现了几个性能优化的关键点虚拟化列表对时间选择部分的ListBox启用虚拟化ListBox VirtualizingStackPanel.IsVirtualizingTrue VirtualizingStackPanel.VirtualizationModeRecycling/延迟加载Popup内容在第一次打开时再初始化绑定优化使用高效的绑定方式// 避免频繁触发PropertyChanged public string DisplayText { get { return _displayText; } set { if (_displayText value) return; _displayText value; OnPropertyChanged(); } }6. 测试策略为确保控件质量我建立了以下测试方案单元测试验证核心逻辑日期时间转换边界条件处理UI自动化测试模拟用户操作验证视觉状态性能测试加载时间内存占用[TestMethod] public void TestDateTimeConversion() { var picker new DateTimePicker(); picker.SelectedDateTime new DateTime(2023, 1, 1, 12, 30, 45); Assert.AreEqual(12, picker.SelectedHour); Assert.AreEqual(30, picker.SelectedMinute); Assert.AreEqual(45, picker.SelectedSecond); }7. 实际应用中的反馈与迭代上线后收集到的用户反馈促成了几个重要改进添加清空按钮允许用户清除已选时间快捷键支持Ctrl点击快速选择当前时间输入验证防止输入非法日期private void OnTextInput(object sender, TextCompositionEventArgs e) { // 验证输入是否为有效时间字符 if (!char.IsDigit(e.Text, 0) e.Text ! :) { e.Handled true; } }在项目中使用这个自定义控件后用户对时间选择的满意度明显提升。最让我意外的是这个控件后来被用在了公司多个产品线中甚至有些同事基于它做了进一步的定制开发。

相关文章:

WPF自定义控件实战:从用户吐槽到优雅实现——我的DateTimePicker开发踩坑记

WPF自定义控件实战:从用户吐槽到优雅实现——我的DateTimePicker开发踩坑记 那天产品经理拍着桌子说:"我们的用户需要精确到秒的时间选择!"我看了看系统里那个老旧的DatePicker,只能显示年月日,心里默默叹了…...

数学建模国赛C题:从模拟退火到NSGA-II,多目标优化算法实战对比与选型指南

数学建模国赛C题:从模拟退火到NSGA-II,多目标优化算法实战对比与选型指南 在数学建模竞赛中,优化问题一直是核心难点之一。面对复杂的多约束、多目标场景,如何选择合适的算法往往决定了模型的成败。本文将深入剖析三种主流优化算法…...

边缘计算与生成式AI:Jetson平台实战解析

1. 在边缘设备上实现生成式AI的突破性实践 NVIDIA Jetson平台正在彻底改变生成式AI的应用范式。作为一名长期从事边缘AI开发的工程师,我亲历了从云端依赖到本地化部署的转变过程。Jetson AGX Orin这类边缘设备的出现,让我们能够在终端设备上直接运行Llam…...

手把手教你用STM32F103的SPI2驱动FPGA(附Verilog从机代码)

STM32与FPGA的SPI通信实战:从硬件连接到代码调试全解析 在嵌入式系统开发中,处理器与可编程逻辑器件的协同工作变得越来越常见。STM32作为广泛使用的微控制器,与FPGA的高速通信是实现复杂系统功能的关键。本文将带你从零开始,完成…...

如何快速搭建NAS媒体库自动化管理工具:5步完整指南

如何快速搭建NAS媒体库自动化管理工具:5步完整指南 【免费下载链接】MoviePilot NAS媒体库自动化管理工具 项目地址: https://gitcode.com/gh_mirrors/mo/MoviePilot MoviePilot是一款专注于NAS媒体库自动化管理的开源工具,它能够智能整理电影和电…...

从LeGO-LOAM到FAST-LIO2:Patchwork地面分割如何提升SLAM建图与定位精度?

Patchwork地面分割算法在激光SLAM中的实战优化:从原理到性能提升 激光雷达SLAM技术正面临复杂环境下的新挑战——如何从海量点云中快速准确地分离地面点,成为提升建图与定位精度的关键。传统均匀网格划分方法在远距离区域容易失效,而Patchwor…...

告别.hex和.axf:用STM32CubeProgrammer给Nucleo板烧录.bin固件的完整指南

告别.hex和.axf:用STM32CubeProgrammer给Nucleo板烧录.bin固件的完整指南 在嵌入式开发中,固件烧录是每个开发者必须掌握的基本技能。对于ST Nucleo系列开发板的用户来说,虽然Keil MDK或IAR等IDE提供了便捷的一键下载功能,但在实…...

从Houdini到UE5:VAT顶点动画纹理的‘黑盒’揭秘与自定义Shader进阶指南

从Houdini到UE5:VAT顶点动画纹理的‘黑盒’揭秘与自定义Shader进阶指南 在影视级实时特效领域,顶点动画纹理(Vertex Animation Texture)技术正逐渐成为连接DCC工具与游戏引擎的桥梁。当传统骨骼动画难以应对复杂物理模拟&#xff…...

ADAPT-VQE算法:量子计算中的自适应变分本征求解器

1. ADAPT-VQE算法概述ADAPT-VQE(Adaptive Derivative-Assembled Pseudo-Trotter Variational Quantum Eigensolver)是一种改进的变分量子本征求解器算法,专为量子计算机设计用于高效模拟量子多体系统的基态性质。与传统VQE使用固定参数化量子…...

GPU云定价新模型:特征定价(FBP)的经济学设计与实践

1. GPU云定价困境:当摩尔定律不再均衡现代GPU架构正在经历一场静默的经济危机。过去五十年间,摩尔定律不仅预测了处理器性能的指数级增长,也保证了每美元能买到的计算能力持续提升。但在今天的GPU领域,这个经济规律出现了戏剧性的…...

AI通过MRI革新帕金森病诊断:技术原理与临床价值

1. AI如何通过常规MRI扫描革新帕金森病诊断作为一名长期关注医疗AI应用的从业者,最近佛罗里达大学团队开发的AIDP平台让我眼前一亮。这个基于深度学习的系统能够从常规MRI扫描中识别帕金森病(PD)、多系统萎缩(MSA)和进…...

告别玄学:STM32H7系列SPI驱动TFT屏的完整配置清单与稳定性实战指南

STM32H7系列SPI驱动TFT屏的黄金配置法则与稳定性实战 记得第一次用STM32H750驱动SPI接口的TFT屏时,那种从兴奋到困惑再到恍然大悟的心路历程至今难忘。屏幕在调试时表现良好,一旦脱离调试环境就频繁黑屏,这种"玄学"问题困扰了我整整…...

别再只用MSE了!NeurIPS 2021新思路:用‘不确定性’给图像超分模型加个‘注意力’,实测EDSR/RCAN效果提升

超越MSE:用不确定性驱动损失重塑图像超分辨率训练范式 当你在深夜调试一个超分辨率模型时,是否也曾对着那些模糊的纹理区域陷入沉思?传统MSE损失平等对待每个像素的"民主原则",恰恰成为了制约模型突破的瓶颈。2021年Neu…...

别再手动挖洞了!用fscan这款开源神器,5分钟搞定内网资产梳理与高危漏洞初筛

内网渗透效率革命:如何用fscan实现一键式资产发现与漏洞定位 当你在凌晨两点接到紧急渗透测试任务时,是否还在为繁琐的手动信息收集而头疼?传统的内网渗透流程往往需要组合多个工具:先用nmap扫描存活主机,再针对开放端…...

给汽车装上“黑匣子”:聊聊国标GB 39732-2020 EDR标准里那些工程师必须知道的细节

汽车EDR系统实战指南:从国标GB 39732到工程落地的关键设计 当一辆汽车发生碰撞事故后,如何准确还原事故发生前后的关键数据?这个问题困扰了汽车工程师和事故调查人员数十年。随着GB 39732-2020标准的实施,中国的汽车电子工程师们迎…...

Pix4Dmapper+ENVI实战:5分钟搞定多光谱图像土壤背景自动剔除(附完整流程)

Pix4Dmapper与ENVI协同实战:多光谱图像土壤背景高效剔除全流程解析 当无人机搭载多光谱传感器飞越农田上空时,那些看似普通的图像数据里,藏着作物长势、土壤墒情、病虫害分布的宝贵信息。但如何从包含土壤背景的原始图像中,精准提…...

保姆级教程:手把手教你用Ventoy制作Windows 11 23H2多合一启动盘(含镜像校验与驱动准备)

实战指南:打造全能Windows 11 23H2系统安装盘的进阶技巧 最近帮朋友重装系统时遇到一个尴尬场景——好不容易做好启动盘,安装时却发现镜像损坏;装完系统又因为缺少网卡驱动连不上网络。这种"经典翻车"在技术圈屡见不鲜,…...

LibreVNA完全指南:从入门到精通的开源矢量网络分析仪使用教程

LibreVNA完全指南:从入门到精通的开源矢量网络分析仪使用教程 【免费下载链接】LibreVNA 100kHz to 6GHz 2 port USB based VNA 项目地址: https://gitcode.com/gh_mirrors/li/LibreVNA LibreVNA是一款功能强大的开源矢量网络分析仪,覆盖100kHz至…...

Beyond Compare 5密钥生成器:三步实现永久激活的完整指南

Beyond Compare 5密钥生成器:三步实现永久激活的完整指南 【免费下载链接】BCompare_Keygen Keygen for BCompare 5 项目地址: https://gitcode.com/gh_mirrors/bc/BCompare_Keygen 还在为Beyond Compare 5的30天评估期到期而烦恼吗?想要免费获得…...

HTTrack跨平台实战手册:从环境配置到高级镜像的完整指南

HTTrack跨平台实战手册:从环境配置到高级镜像的完整指南 【免费下载链接】httrack HTTrack Website Copier, copy websites to your computer (Official repository) 项目地址: https://gitcode.com/gh_mirrors/ht/httrack HTTrack网站镜像工具是一款功能强大…...

FPGA加速器架构优化与DNN推理性能提升

1. FPGA加速器架构概述深度神经网络(DNN)推理对计算资源的需求呈指数级增长,传统CPU/GPU方案在能效比和实时性方面面临严峻挑战。我们设计的FPGA加速器架构针对通用矩阵乘法(GEMM)运算进行了深度优化,这是D…...

PLC交通灯控制:博途V15与S7-1200的‘比较指令‘编程与触摸屏调试实践

PLC交通灯控制,博途V15,S7-1200 使用比较指令,程序完整,触摸屏调试正常,触摸屏上有倒计时显示功能。 有两份对应实训报告(设计说明书),包括每段程序原理解释,触摸屏设置过程&#xf…...

别再手动调格式了!用SciencePlots一键搞定Nature/IEEE论文图表(附中文乱码终极解决方案)

科研绘图革命:用SciencePlots实现期刊级图表自动化 凌晨三点的实验室,屏幕上闪烁的是一张即将投稿的图表——本该完美的曲线被密密麻麻的方框取代,所有中文标注消失无踪。这不是恐怖片场景,而是每个科研工作者都经历过的真实噩梦。…...

Vue 3 中集成 Three.js 场景的完整实现指南

本文详细讲解如何在 vue 3(javascript 版本)项目中正确集成 three.js,完成基础 3d 场景渲染,涵盖 dom 挂载时机、渲染循环管理、响应式容器适配等关键实践。 本文详细讲解如何在 vue 3(javascript 版本&#xff0…...

手机没网也能用!聊聊语音唤醒KWS技术是怎么在本地‘偷偷’工作的

手机没网也能用!揭秘语音唤醒技术如何在本地悄然工作 记得上次在地铁隧道里,手机信号全无,却依然能用"Hey Siri"唤醒语音助手时的惊讶吗?这种看似简单的功能背后,是语音唤醒技术(KWS)…...

Golang怎么做代码热更新_Golang热更新教程【精通】

Go程序无法真正热更新,所谓“热更新”实为外部工具触发的平滑重启或模块重载;fsnotify监听go run仅适用于本地开发,存在进程丢失、请求中断、路径敏感、启动慢、信号与环境变量无法透传等问题。Go 程序根本不能“热更新”,别被名字…...

从‘端点效应’到‘必要性探路’:一个被忽视的数学思想如何简化复杂不等式证明

从“端点效应”到“必要性探路”:数学不等式证明中的思维跃迁 数学证明的本质,往往不在于繁琐的计算,而在于找到那条隐藏的逻辑捷径。当我们面对一个复杂的不等式证明时,常常会陷入盲目求导或机械变形的困境。而“端点效应”这一看…...

Docker Desktop已禁用!国产化替代方案紧急上线:5款可商用容器运行时横向测评(含openEuler 24.09实测吞吐量对比)

第一章:Docker Desktop禁用背景与国产化替代紧迫性分析2023年1月,Docker官方更新《服务条款》,明确禁止在企业生产环境中免费使用Docker Desktop,且要求商业用户必须订阅付费许可证。该政策直接影响国内大量依赖Docker Desktop进行…...

从GPU到TSP:Groq的“功能切片”架构如何让AI推理快人一步?

从GPU到TSP:Groq的“功能切片”架构如何让AI推理快人一步? 当你在电商平台搜索商品时,是否想过背后支撑实时推荐系统的AI模型如何在毫秒间完成推理?传统GPU架构在训练阶段表现出色,却在实时推理场景中暴露出能效低下、…...

NVIDIA DGX GH200超级计算机架构与性能解析

1. NVIDIA DGX GH200 超级计算机架构解析在2023年台北国际电脑展上,NVIDIA发布了革命性的DGX GH200超级计算机系统,这是首个突破100TB GPU内存壁垒的计算平台。作为一名长期跟踪GPU计算架构演进的从业者,我认为这一创新将彻底改变超大规模AI模…...