模拟实现WPF的依赖属性及绑定通知机制(3)--依赖对象

第四章:WPF依赖/附加属性,数据绑定(一) WPF 依赖属性,附加属性,数据绑定,数据转换 阅读详情

下面是依赖对像类的实现:(注,这里涉及到INotifyPropertyChanged接口,大家可以参考MSDN文档了解).

 /// <summary>
    /// 依赖对像,主要提供属性值和属性绑定的管理。
    /// </summary>
    public class MyDependencyObject
    {
        private IDictionary<MyDependencyProperty, object> _dict = new Dictionary<MyDependencyProperty, object>();
        private IDictionary<MyDependencyProperty, MyBinding> _bindings = new Dictionary<MyDependencyProperty, MyBinding>();
        public void SetValue(MyDependencyProperty p, object val)
        {
           
            //如果设置值是默认值,则可不保存,以节省空间.
            object theOldValue = null;
            if (_dict.ContainsKey(p))
            {
                theOldValue = _dict[p];
                //如果已有设置值,且等于当前设置值,则退出
                if (theOldValue == val)
                {
                    return;
                }
                //如果设置值等于默认值,则删除已有的设置值。
                if (p.DefaultValue == val)
                {
                    _dict.Remove(p);
                    return;
                }
                //设置新的字典值
                _dict[p] = val;
            }
            else
            {
                //如果设置值不等于默认值,则增加设置值,否则不做任何设置。
                if (p.DefaultValue != val)
                {
                    _dict.Add(p, val);
                }
                else
                {
                    return;
                }
               
            }
           
            if (p.PropertyMetadata != null && p.PropertyMetadata.PropertyChangedCallback != null)
            {
                MyDependencyPropertyChangedEventArgs theArgs =
                    new MyDependencyPropertyChangedEventArgs(val, theOldValue, p);
                p.PropertyMetadata.PropertyChangedCallback(this, theArgs);
            }
            //如果是双向绑定,则需要同步数据到绑定数据源,这里假设需要双向绑定.
            if (_bindings.ContainsKey(p) == true)
            {
                MyBinding theBinding = _bindings[p];
                if (theBinding.TargetObject != null && theBinding.PropertyName != "")
                {
                    System.Reflection.PropertyInfo thePI = theBinding.TargetObject.GetType().GetProperty(theBinding.PropertyName);
                    if (thePI != null && thePI.CanWrite==true)
                    {
                        //对于有索引的设置值比较复杂一点,可利用反射来进行,这里只是演示简单属性。
                        //注意,如果目标类实现了INotifyPropertyChanged接口,并有修改触发机制,那么这里的设置
                        //会触发目标属性改变事件,就会触发MyDependencyObject_PropertyChanged执行,
                        //而MyDependencyObject_PropertyChanged里又调用了SetValue函数,这就会死循环,这也是
                        //为什么前面的代码中为什么要判断如果已经有的设置值等于当前设置新值直接退出的缘故,就是
                        //为了阻止死循环.当然,在目标属性中set里面做判断也可以,但这里一定要做,
                        //原因大家可以自己想一下。
                        thePI.SetValue(theBinding.TargetObject, val, null);
                    }
                }
            }
        }

        public object GetValue(MyDependencyProperty p)
        {
            //如果被动画控制,返回动画计算值。(可能会用到p.Name)

            //如果有本地值,返回本地值
            if (_dict.ContainsKey(p))
            {
                return _dict[p];
            }

            //如果有Style,则返回Style的值

            //返回从可视化树中继承的值

            //最后, 返回依赖属性的DefaultValue
            return p.DefaultValue;
        }
        /// <summary>
        /// 设置绑定属性,一样是模拟微软的干活,只不过微软的这个方法不是在依赖对象里实现的,
        /// 而是在UIElement里实现的.
        /// </summary>
        /// <param name="p"></param>
        /// <param name="Binding"></param>
        public void SetBinding(MyDependencyProperty p, MyBinding Binding)
        {
            MyBinding theOld = null;
            //需要先将老的绑定找到并记录,因为需要解除挂接.
            if (_bindings.ContainsKey(p))
            {
                theOld = _bindings[p];
                _bindings[p] = Binding;
            }
            else
            {
                _bindings.Add(p, Binding);
            }
            //删除旧的绑定.
            if (theOld != null)
            {
                if (theOld.TargetObject is INotifyPropertyChanged)
                {
                    ((INotifyPropertyChanged)theOld.TargetObject).PropertyChanged -= new PropertyChangedEventHandler(MyDependencyObject_PropertyChanged);
                }
            }

            //如果是单向绑定或者双向绑定则需要以下挂接。如果只是Onetime则不必要.
            if (Binding.TargetObject is INotifyPropertyChanged)
            {
                ((INotifyPropertyChanged)Binding.TargetObject).PropertyChanged += new PropertyChangedEventHandler(MyDependencyObject_PropertyChanged);
            }

        }
        /// <summary>
        /// 目标属性发生变化时的处理事件方法。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void MyDependencyObject_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            MyDependencyProperty p = null;
            //找到绑定属性所在的依赖属性
            foreach (var b in _bindings)
            {
                if (b.Value.PropertyName == e.PropertyName)
                {
                    p = b.Key;
                    break;
                }
            }
            //不为空则处理.
            if (p != null)
            {
                System.Reflection.PropertyInfo thePI = sender.GetType().GetProperty(e.PropertyName);
                if (thePI != null && thePI.CanRead == true)
                {
                    object theVal = thePI.GetValue(sender, null);
                    SetValue(p, theVal);
                    //如果目标类INotifyPropertyChanged,绑定模式是ontime,则下面的代码就是要接触与目标属性的挂接.
                    if (sender is INotifyPropertyChanged)
                    {
                        ((INotifyPropertyChanged)sender).PropertyChanged += new PropertyChangedEventHandler(MyDependencyObject_PropertyChanged);
                    }
                }
            }
        }
    }

 

为了实现依赖属性和绑定属性之间的连动,SetBinding方法至关重要,大家仔细看.

WPF双向绑定 一.WPF双向绑定 1.1下载Mvvm配置 点击工具 NuGet ,选择中间的管理解决方案包,查询Mvvm选择MvvmLight 和MvvmLight libraries only进行安装。不能马上关闭网络,需要网络加载引用。 继承MVVM :ViewModelBase 上下文DataContext 1.2 数据库服器名字 (local) sa 本机名称 1.3 双向绑定 RaisePropertyChanged *图片用BitmapImage 普通类型用string ... 阅读详情

相关推荐

纯C#实现WPF核心机制——附加属性与数据绑定详解(第1部分)

附加属性本质上是一种“外部标签”机制。它允许某个服务类(如Canvas)为任意其他对象附加元数据信息,而无需修改目标类的结构。这种设计打破了封装边界,却带来了极高的灵活性。举个生活化的比喻:就像你在机场托运行李时贴上的航班标签。箱子本身并不知道目的地,但分拣系统可以通过读取标签决定它的去向。同理,Canvas不关心按钮内部结构,只要它能“看到”Left这个标签,就知道该把它摆在哪里。var button = new Button { Content = "点我" };

weixin_35752645的博客 808

WPF 入门笔记 - 05 - 依赖属性

有了这个,依赖项属性不用写额外的代码,也不用实现什么接口,它本身就俱备双向绑定的特性,比如把员工对象的姓名绑定到文本框,一旦绑定,只要文本框中的值发生改变,依赖项属性员工姓名也会跟着变化,反之亦然;自定义依赖属性的步骤中,最重要的就是依赖属性的注册,定义的公共属性仅仅提供我们访问依赖属性的便捷方法,不写也是可以的,只不过我们得在每次使用依赖属性的时候都调用。第一个参数是该依赖属性的名字,第二个参数是依赖属性的类型,第三个参数是该依赖属性的所有者的类型,第五个参数是一个验证值的回调委托,第四个。

woaimx_1314的博客 1616

OpenCV+ArUco实战:如何用Python实现高精度二维码测距(附完整代码)

本文详细介绍了如何使用Python和OpenCV实现基于ArUco标签的高精度单目视觉测距。通过相机标定、标签检测和三维位置估算,结合完整代码示例,帮助开发者在机器人导航、工业自动化等场景中实现厘米级距离测量,并探讨了精度优化与三维可视化等进阶应用。

weixin_29052717的博客 478

WPF真入门教程17--双向数据绑定

在这里的示例,要学习一下双向绑定的模式TwoWay,和更新触发模式UpdateSourceTrigger的使用效果。这个示例是根据ListBox中的选中项,去改变TextBlock的背景色和TextBox的显示内容及背景色,也可以输入颜色类型,(注意不能输入中文,中文不认识)。代码如下(代码是接上一节的代码继续添加的)。

hqwest的专栏 2347

告别轮询!用STM32CubeMX给STM32F030配置ADC多通道+DMA,实测代码分享

本文详细介绍了如何使用STM32CubeMX为STM32F030配置ADC多通道采集与DMA传输,显著提升采集效率。通过实测对比轮询与DMA模式的性能差异,提供完整的代码实现和优化技巧,帮助开发者快速掌握这一高效采集方案。

weixin_42570296的博客 410

PADS VX2.4 缝合孔(阵列过孔)的添加方法

缝合孔的主要目的是:①:增加底层和顶层的地铜皮的连接性,②:起到屏蔽外界信号干扰的作用。铺完铜后,右击空区域选择“选择形状”命令,选取整板中的一块大铜皮,右击选择“覆铜区域内过孔阵列模式”→“沿周边”指令后,再右击选择“覆铜区域内过孔阵列”,便能看到已选区域内添加的缝合孔(过孔阵列),也可以通过铜皮显示或隐藏的无模命令:PO进行查看。完成上面的“防止错误”和“过孔样式”的设置后,开始对整板进行铺铜处理,点击“工具栏”→覆铜平面指示器,在弹出的对话框点击“开始”,便能观察铺铜后的板子。

tianpu2320959696的博客 3057

模拟实现WPF的依赖属性及绑定通知机制(2)--依赖对象的准备

依赖对象一个主要的功能就是提供对依赖属性属性值的管理,所有需要具有依赖属性的类都可以从这里继承,而无需自己去管理依赖属性值。依赖对象的主要方法就是SetValue和GetValue两个方法,这也是依赖属性和普通属性获取值不一样的地方,当然实际的应用中依赖属性一般不会直接使用这两个

三人行必有我师,手写三行必有所悟 5039

VL53L1X vs VL53L0X:激光测距传感器选型指南与性能对比

本文深入对比了VL53L1X与VL53L0X两款激光测距传感器的核心差异。VL53L1X采用区域ToF原理,在抗环境光干扰、最大测距及多目标识别方面优势显著,尤其适合复杂光线与动态场景。文章结合机器人避障、无人机定高等实战场景,提供了清晰的选型决策树,帮助工程师根据测距需求、环境复杂度与系统成本做出最优选择。

weixin_29197699的博客 394

WPF依赖属性,绑定通知机制系列补充说明

依赖对象准备增加了属性元数据类型的定义,开始忘记贴了。以上代码都经过了测试,模拟是成功的。其实微软在页面中的绑定语法最终都会如模拟中那样实现。微软的做法是导入xaml文件的时候根据文件中的控件语法动态的生成控件实例,其绑定语法也是在这个过程中自动添加进出的,只不过需要一个简单的路

三人行必有我师,手写三行必有所悟 5224

宇瞳杯视讯镜头完成版(除公差/鬼像分析)

宇瞳杯视讯镜头完成版(除公差/鬼像分析)

weixin_72050316的博客 1049

基于MATLAB的脑功能网络工具箱:BCT与FCLab

脑功能网络分析是神经科学领域的一个重要研究方向,它通过分析大脑中神经元之间的连接模式和信息传递方式,揭示脑网络的结构和功能。在这个领域,MATLAB是一个广泛使用的工具,提供了丰富的函数和工具箱来进行脑功能网络的分析和可视化。这些工具箱提供了丰富的函数和工具,使得脑功能网络的计算和分析变得更加简单和高效。在上述示例代码中,我们首先导入BCT工具箱,并构建一个邻接矩阵来表示脑网络的连接关系。在上述示例代码中,我们首先导入FCLab工具箱,并导入脑功能数据。函数对数据进行预处理,如去除噪声、降采样等操作。

web_bug407的博客 2611

模拟实现WPF的依赖属性及绑定通知机制(4)--模拟实现绑定连动机制

1、一个依赖对象示例: public class MyDendencyControl : MyDependencyObject { public static readonly MyDependencyProperty ContentDependencyProper...

chengyixian7877的博客 86

地表最强之Android微信语音/腾讯会议通话录音

地表最强之Android微信语音/腾讯会议通话录音

cczhengv 6108

模拟实现WPF的依赖属性及绑定通知机制(1)--依赖属性

依赖属性的好处大家可以参见前面我转载的博文。我们知道,WPF中控件的属性非常多,但这些属性中大部分你在编程过程中是不会改变设置的,而是直接利用其默认值(所以以后设计属性时,默认值的选择也非常关键,这有利于减少存储),如果采用原来的属性方式,每个类的实例都会有自己的一份属性值集合,

三人行必有我师,手写三行必有所悟 4970

1、使用Spark SQL查询Databricks:全面指南

本博客全面介绍了如何使用Spark SQL在Databricks平台上进行高效的数据查询与分析。内容涵盖SQL基础操作、数据过滤、复杂查询技巧、简单与高级计算、数据聚合、日期处理等核心主题,适合数据分析师、开发人员及SQL学习者。通过逐步讲解和实用示例,帮助读者掌握从入门到高级的SQL技能,并提供学习路径建议和免费代码资源,助力实际数据分析工作。

redis7keeper的博客 91

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

模拟实现WPF的依赖属性及绑定通知机制(4)--模拟实现绑定连动机制 .

1、一个依赖对象示例:  public class MyDendencyControl : MyDependencyObject     {         public static readonly MyDependencyProperty ContentDependencyProperty =             MyDependencyProperty.Register("Co

蓝叶菱的专栏 1127

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

上一篇: 模拟实现WPF的依赖属性及绑定通知机制(2)--依赖对象的准备
下一篇: 模拟实现WPF的依赖属性及绑定通知机制(4)--模拟实现绑定连动机制
广州接入
广州接入 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄24年 2224粉丝 731原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值