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

WPF Telerik.Windows.Controls.Data.PropertyGrid 自定义属性编辑器

1.AI帮忙定义新用户控件

2.在属性上添加TelerikEditorAttribute特性

 private ObservableCollection<string> _axisOrder;[Display(Description = "点位", GroupName = "通用", Name = "轴&顺序", Order = 1)][DataMember][TelerikEditorAttribute(typeof(DoubleListBoxEditor), "SelectedItems")]public ObservableCollection<string> AxisOrder{get => _axisOrder;set => this.RaiseAndSetIfChanged(ref _axisOrder, value);}
[TelerikEditorAttribute(typeof(DoubleListBoxEditor), "SelectedItems")]

SelectedItems属性可以根据实体情况进行更换;

3.效果

4.扩展

这个编辑控件包含了两个ListBox,我想根据实体的其他属性变更然后变更其中一个ListBox的数据源:

思路就是在DoubleListBoxEditor类里面监听这个属性变化,要挂载事件;

要想找到这个属性的事件就得找到对应的实体;

(要有控件的Parent属性, 视觉树这些概念)

使用自定义Editor控件的Parent属性,可以得到对应的在PropertyGrid中对应的条目包装:

在这个包装中找到DataContext属性得到对应的实体属性包装;

然后再找到Instance属性得到对应实体,再得到对应想拿到的属性;

挂载事件的时机要把控好,不能写在构造函数里,此时界面对象还未赋值;

代码:

  public override void OnApplyTemplate(){base.OnApplyTemplate();if (!(Parent is PropertyGridField field)){return;}var def = (PropertyDefinition)field.DataContext;CustomPropertyDescriptor pd = null;if (def.Instance is MovePositionActionNode node){node.PropertyChanged -= PositionPropertyChanged;node.PropertyChanged += PositionPropertyChanged;}}

更新:

测试中发现会多次调用PositionPropertyChanged方法,和我预想的结果不同,因为我的写法是:

node.PropertyChanged -= PositionPropertyChanged;
 node.PropertyChanged += PositionPropertyChanged;

本来想的是始终只会挂载一个方法上去,但是测试的时候发现每调用一次OnApplyTemplate(),就会多挂载一个方法上去。

原因:

在 C# 中,委托实际上是对象(继承自 System.MulticastDelegate)。每次使用方法名创建委托时,都会在堆上创建一个新的委托对象实例。

写一段代码模拟上面出现的bug:

 public class EventSource{public event EventHandler Event;public void RaiseEvent(){Event.Invoke(null,null);}}public class Example{public void MyMethod(object sender, EventArgs e) { Console.WriteLine("Hello, World!"); }}

然后这样调用:

 EventSource obj = new EventSource();for (int i = 0; i < 3; i++){Example ex = new Example();obj.Event -= ex.MyMethod;obj.Event += ex.MyMethod;}obj.RaiseEvent();

结果会调用三次MyMethod,因为我的代码中,执行OnApplyTemplate时都是新创建对象的时候,所以效果类似这段测试代码;

查看IL:

node.PropertyChanged -= PositionPropertyChanged;
 node.PropertyChanged += PositionPropertyChanged;

  IL_0045: ldloc.2      // nodeIL_0046: ldarg.0      // thisIL_0047: ldftn        instance void Lithography.Model.ActionAbout.UI.DoubleListBoxEditor::PositionPropertyChanged(object, class [System]System.ComponentModel.PropertyChangedEventArgs)IL_004d: newobj       instance void [System]System.ComponentModel.PropertyChangedEventHandler::.ctor(object, native int)IL_0052: callvirt     instance void [ReactiveUI]ReactiveUI.ReactiveObject::remove_PropertyChanged(class [System]System.ComponentModel.PropertyChangedEventHandler)IL_0057: nop// [82 17 - 82 65]IL_0058: ldloc.2      // nodeIL_0059: ldarg.0      // thisIL_005a: ldftn        instance void Lithography.Model.ActionAbout.UI.DoubleListBoxEditor::PositionPropertyChanged(object, class [System]System.ComponentModel.PropertyChangedEventArgs)IL_0060: newobj       instance void [System]System.ComponentModel.PropertyChangedEventHandler::.ctor(object, native int)IL_0065: callvirt     instance void [ReactiveUI]ReactiveUI.ReactiveObject::add_PropertyChanged(class [System]System.ComponentModel.PropertyChangedEventHandler)IL_006a: nop

挂载对象前创建了一个PropertyChangedEventHandler对象,对应着上方:委托实际上是对象(继承自 System.MulticastDelegate)。每次使用方法名创建委托时,都会在堆上创建一个新的委托对象实例。

也就是说+=操作符相当于执行了Add_TestEvent(new Action(memory.Run)),就是这个new Action包含了对memory指向的内存的引用。而这个引用在CLR看来是可达的,可以通过引发事件来调用该内存,所以这种情况会有内存泄漏的风险。

引用:https://blog.csdn.net/nodeathphoenix/article/details/84549399?fromshare=blogdetail&sharetype=blogdetail&sharerId=84549399&sharerefer=PC&sharesource=qq_59062726&sharefrom=from_link

解决办法:

未完待续


文章转载自:

http://DOPxBq7C.rfwkn.cn
http://csddmGd5.rfwkn.cn
http://x2ag2Etr.rfwkn.cn
http://LTnryWW6.rfwkn.cn
http://MypceP4X.rfwkn.cn
http://MqvgTKea.rfwkn.cn
http://3yqRJUb6.rfwkn.cn
http://ewyXPqBC.rfwkn.cn
http://IzmH4i61.rfwkn.cn
http://dmDZ3PEN.rfwkn.cn
http://Eb5YO2O6.rfwkn.cn
http://BRh0SuX2.rfwkn.cn
http://UE8Afzbk.rfwkn.cn
http://CD4H3nuT.rfwkn.cn
http://dUGf9kXL.rfwkn.cn
http://ueOhGV5r.rfwkn.cn
http://xucwhI0c.rfwkn.cn
http://QgEDsxsH.rfwkn.cn
http://3AXb89kl.rfwkn.cn
http://gRNph9t9.rfwkn.cn
http://sDCLLrpQ.rfwkn.cn
http://2ZxWpUq4.rfwkn.cn
http://7DpB6Ujz.rfwkn.cn
http://R8PjsbHY.rfwkn.cn
http://yQ83pBdi.rfwkn.cn
http://UtVnMEag.rfwkn.cn
http://TPPUyKAP.rfwkn.cn
http://xadhrASu.rfwkn.cn
http://ZKZVWApK.rfwkn.cn
http://d4A9SA1S.rfwkn.cn
http://www.dtcms.com/a/378020.html

相关文章:

  • 谷歌浏览器多开软件推荐使用运营大管家谷歌浏览器多开软件,效率快!
  • Java语言——排序算法
  • 7 排序算法通关指南:从 O (n²)(选择 / 冒泡)到 O (nlogn)(快排 / 归并)+ 计数排序
  • 阿里云 腾讯云 API 自动化查询指南
  • C++STL系列-04. list和forward_list
  • wpf程序启动居中并且最小化到托盘修复记录
  • 《JVM如何排查OOM》
  • ITP 3.0.0 版本重磅发布:接口测试平台迎来多项重大升级
  • 流式细胞术样本处理全攻略(一):组织、血液、体液制备方法详解
  • 【Ansible】将文件部署到受管主机知识点
  • 3 水平分表
  • ISO20000与IT运维和运营的关系
  • AI生成文本检测数据集:基于不平衡数据集(人类94% vs AI 6%)的高效机器学习模型训练,涵盖ChatGPT、Gemini等LLM生成内容
  • 音视频学习(六十四):avc1 hvc1和hev1
  • JC链客云——项目过程中获得的知识、遇到的问题及解决
  • 新手向:从零理解LTP中文文本处理
  • pyproject.toml 的历史背景和原理
  • vue知识点总结
  • macos arm自动编译x264和x265 Android平台so库
  • 三甲地市级医院数据仓湖数智化建设路径与编程工具选型研究(下)
  • Excel批量处理一列数据---分列功能
  • 从Miniflux 到 NextFlux:一步升级,拥抱现代化阅读体验
  • 机器视觉之图像处理篇
  • Find 命令详解
  • (九)Spring Cloud Alibaba 2023.x:微服务接口文档统一管理与聚合
  • 【C++深学日志】从0开始的C++生活
  • C#---Expression(表达式)
  • DCS控制回路优化:基于WebSocket的实时参数远程调校方法论
  • WebSocket压缩传输优化:机器视觉高清流在DCS中的低延迟方案
  • Java 软件测试(三):Mockito打桩与静态方法模拟解析