WPF入门(2)——依赖属性
今天我们说说依赖属性
什么是依赖属性?
当然,学术定义依旧Please Baidu:https://baike.baidu.com/item/%E4%BE%9D%E8%B5%96%E5%B1%9E%E6%80%A7/637278?fr=aladdin
那么,请问你看明白了吗?明白了就请出门左转吧,同时本人也是很佩服的,本人也是经人点拨后才了解依赖属性到底是个什么东西,他真实的定义就是:
依赖属性——一个反抗旧思想旧家庭的新时代抗争青年(说白了就是个愤青)
先讲一个故事:
贾少爷,姓贾名五代,出身贵族家庭,其父贾老爷,姓贾名四代,著名商旅,其祖父贾爷爷,姓贾名三代,文人墨客,其高祖贾高祖,姓贾名二代,官宦重臣,其先祖贾剑客,姓贾名一代,侠士风流,家中历代均有家产流传给后世。流传图谱如下:
贾一代:隐士剑谱
贾二代:丞相司印
贾三代:风雅画卷
贾四代:金银重鼎
以上四件神器流传至今,均传给了贾五代
结果贾五代是个家族异类,专心研究佛法,手里最看重的宝贝是:念珠木鱼。
这就尴尬了,作为贾少爷,只想研究佛法,那四件价值连城的宝贝根本瞧不上(给我呀……),一心想要和家庭抗争,只想拿着念珠木鱼烧香拜佛,所以这事该怎么办?
好的故事到此结束。
其实这就是依赖属性,每个父类都有其自有属性,当一个子类多级继承其父类时,那么它必然继承了其父类的所有可以继承的成员,所以就会造成最后的一个叶子子类臃肿不堪,本来不想要的属性也因为继承链而被传递给子类。上面的故事用代码解释就是这样的。
public class JiaYidai
{
public string YinShiJianPu { get; set; }
} public class JiaErdai:JiaYidai
{
public string ChengXiangSiYin { get; set; }
} public class JiaSandai : JiaErdai
{
public string FengYaHuaJuan { get; set; }
} public class JiaSidai : JiaSandai
{
public string JinYinZhongDing { get; set; }
} public class JiaWudai : JiaSidai
{
public string NianZhuMuYu { get; set; }
}
那么当我们在调用JiaWudai时肯定会出现之前的父类的属性,如图:
那么那些不相干的属性就会同步继承而来,所以依赖属性就是为了解决这个问题而产生的。
我们来看如何来解决这个问题,既然贾五代不想继承其它的属性,那么我们就将其父类的宝贝都做成依赖属性,看看会怎么样。
首先我们先建立一个依赖属性对象:
public class DependencyProperty
{
/// <summary>
/// 属性名
/// </summary>
internal string Name;
/// <summary>
/// 属性值
/// </summary>
internal object Value; /// <summary>
/// 构造函数
/// </summary>
/// <param name="name"></param>
/// <param name="propertyName"></param>
/// <param name="ownerType"></param>
/// <param name="defaultValue"></param>
private DependencyProperty(string name, Type propertyName, Type ownerType, object defaultValue)
{
this.Name = name;
this.Value = defaultValue;
}
/// <summary>
/// 创建属性的方法
/// </summary>
/// <param name="name"></param>
/// <param name="propertyName"></param>
/// <param name="ownerType"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public static DependencyProperty CreateInstance(string name, Type propertyName, Type ownerType, object defaultValue)
{
DependencyProperty dp = new DependencyProperty(name, propertyName, ownerType, defaultValue);
return dp;
}
}
之后我们再建立贾五代的四个父级类,代码如下
public class JiaYidai
{
public static readonly DependencyProperty InstantYidai = DependencyProperty.CreateInstance("YinShiJianPu", typeof(string), typeof(JiaYidai), "隐士剑谱");
public object GetValueYidai(DependencyProperty dp)
{
return dp.Value;
}
public void SetValueYidai(DependencyProperty dp, string value)
{
dp.Value = value;
}
public string YinShiJianPu
{
get
{
return GetValueYidai(InstantYidai).ToString();
}
set
{
SetValueYidai(InstantYidai, value);
}
}
} public class JiaErdai : JiaYidai
{ public static readonly DependencyProperty InstantErdai = DependencyProperty.CreateInstance("ChengXiangSiYin", typeof(string), typeof(JiaYidai), "丞相司印");
public object GetValueErdai(DependencyProperty dp)
{
return dp.Value;
}
public void SetValueErdai(DependencyProperty dp, string value)
{
dp.Value = value;
}
public string ChengXiangSiYin
{
get
{
return GetValueErdai(InstantErdai).ToString();
}
set
{
SetValueErdai(InstantErdai, value);
}
}
} public class JiaSandai : JiaErdai
{
public static readonly DependencyProperty InstantSandai = DependencyProperty.CreateInstance("FengYaHuaJuan", typeof(string), typeof(JiaYidai), "风雅画卷");
public object GetValueSandai(DependencyProperty dp)
{
return dp.Value;
}
public void SetValueSandai(DependencyProperty dp, string value)
{
dp.Value = value;
}
public string FengYaHuaJuan
{
get
{
return GetValueSandai(InstantSandai).ToString();
}
set
{
SetValueSandai(InstantSandai, value);
}
}
} public class JiaSidai : JiaSandai
{
public static readonly DependencyProperty InstantSidai = DependencyProperty.CreateInstance("JinYinZhongDing", typeof(string), typeof(JiaYidai), "金银重鼎");
public object GetValueSidai(DependencyProperty dp)
{
return dp.Value;
}
public void SetValueSidai(DependencyProperty dp, string value)
{
dp.Value = value;
}
public string JinYinZhongDing
{
get
{
return GetValueErdai(InstantErdai).ToString();
}
set
{
SetValueErdai(InstantErdai, value);
}
}
}
然后我们再次调用
咦,为什么没有变化呢?查看源代码就会发现我们为了调用的方便,我们在依赖属性的SetValue和GetValue方法后封装了一个public的同名属性,这个属性是可以继承的,所以贾五代依旧可以看到并使用这些属性。可以通过删除父级类中的属性进行测试,在从不再详述。当然如果真的希望各个属性间不发生任何属性继承,可以取消所有继承,让各级父类分别继承这五个依赖属性,就可以实现类构成的精简
那么这个依赖属性有什么用?让我们看另外一个例子,代码如下:
public class JiaYidai
{
private static DependencyProperty Instant = DependencyProperty.CreateInstance("YinShiJianPu", typeof(string), typeof(JiaYidai), "隐士剑谱");
public object GetValueYidai(DependencyProperty dp)
{
return dp.Value;
}
public void SetValueYidai(DependencyProperty dp, string value)
{
dp.Value = value;
}
public string YinShiJianPu
{
get
{
return GetValueYidai(Instant).ToString();
}
set
{
SetValueYidai(Instant, value);
}
}
} public class JiaErdai : JiaYidai
{ private static DependencyProperty Instant = DependencyProperty.CreateInstance("ChengXiangSiYin", typeof(string), typeof(JiaYidai), "丞相司印");
public object GetValueErdai(DependencyProperty dp)
{
return dp.Value;
}
public void SetValueErdai(DependencyProperty dp, string value)
{
dp.Value = value;
}
public string ChengXiangSiYin
{
get
{
return GetValueErdai(Instant).ToString();
}
set
{
SetValueErdai(Instant, value);
}
}
} public class JiaSandai : JiaErdai
{
private static DependencyProperty Instant = DependencyProperty.CreateInstance("FengYaHuaJuan", typeof(string), typeof(JiaYidai), "风雅画卷");
public object GetValueSandai(DependencyProperty dp)
{
return dp.Value;
}
public void SetValueSandai(DependencyProperty dp, string value)
{
dp.Value = value;
}
public string FengYaHuaJuan
{
get
{
return GetValueSandai(Instant).ToString();
}
set
{
SetValueSandai(Instant, value);
}
}
} public class JiaSidai : JiaSandai
{
private static DependencyProperty Instant = DependencyProperty.CreateInstance("JinYinZhongDing", typeof(string), typeof(JiaYidai), "金银重鼎");
public object GetValueSidai(DependencyProperty dp)
{
return dp.Value;
}
public void SetValueSidai(DependencyProperty dp, string value)
{
dp.Value = value;
}
public string JinYinZhongDing
{
get
{
return GetValueErdai(Instant).ToString();
}
set
{
SetValueErdai(Instant, value);
}
}
} public class JiaWudai : JiaSidai
{
public string NianZhuMuYu { get; set; }
}
再运行如图所示代码:
看结果:
咦,本来改的是子类,怎么把父类给改了?没错这就是依赖属性的好处,一处修改,大家都知道了,想想也知道,假如贾五代这天闲来无事,打开了风雅画卷,突然无聊,拿起笔来在画卷上写了个hello world,然后把画卷收回去了,他的祖父贾三代再拿出来打开的时候hello world会没了么?写上了不擦肯定不会消失的,这就是依赖属性的好处。
所以如果依赖属性和使用了依赖属性的对象再继承一个接口INotifyPropertyChanged的话,好像……诞生了一个新的世界,这个世界让我们下回分解……
WPF入门(2)——依赖属性的更多相关文章
- WPF 精修篇 依赖属性
原文:WPF 精修篇 依赖属性 依赖属性使用场景 1. 希望可在样式中设置属性. 2. 希望属性支持数据绑定. 3. 希望可使用动态资源引用设置属性. 4. 希望从元素树中的父元素自动继承属性值. 5 ...
- WPF中的依赖属性
1. WPF中的依赖属性 依赖属性是专门基于WPF创建的.在WPF库实现中,依赖属性使用普通的C#属性进行了包装,使用方法与普通的属性是相同的. 1.1 依赖属性提供的属性功能 资源 数据绑定 样式 ...
- WPF学习笔记——依赖属性(Dependency Property)
1.什么是依赖属性 依赖属性是一种可以自己没有值,并且通过Binding从数据源获得值(依赖在别人身上)的属性,拥有依赖属性的对象被称为"依赖对象". 依赖项属性通过调用 Regi ...
- WPF教程:依赖属性
一.什么是依赖属性 依赖属性就是一种自己可以没有值,并且可以通过绑定从其他数据源获取值.依赖属性可支持WPF中的样式设置.数据绑定.继承.动画及默认值. 将所有的属性都设置为依赖属性并不总是正确的解决 ...
- [No000012D]WPF(5/7)依赖属性
介绍 WPF带来了很多传统 Windows 应用程序没有的新特性和选择.我们已经讨论了一些 WPF 的特性,是时候更进一步介绍其他特性了.当你读完这个系列之前的文章,我希望你已经或多或少地了解了 WP ...
- (原创)2. WPF中的依赖属性之二
1 依赖属性 1.1 依赖属性最终值的选用 WPF属性系统对依赖属性操作的基本步骤如下: 第一,确定Base Value,对同一个属性的赋值可能发生在很多地方.还用Button的宽度来进行举例,可能在 ...
- 【转】【WPF】关于依赖属性的ValidateValueCallback,PropertyChangedCallback和CoerceValueCallback的执行顺序
三个回调对应依赖属性的验证过程,改变过程和强制转换过程. class Dobj : DependencyObject { //依赖属性包装 public int MyProperty { get { ...
- WPF usercontrol 自定义依赖属性
1.依赖属性不同意一般属性,一般属性主要定义在对象中,而依赖属性是存在一个特殊的依赖属性表中.2.当我们触发改变值时,需要通过SetValue这种方式进行触发. UserControl1.xaml: ...
- WPF 主动触发依赖属性的 PropertyChanged
需求背景 需要显示 ViewModel 中的 Message/DpMessage,显示内容根据其某些属性来确定.代码结构抽象如下: // Model public class Message : IN ...
- WPF快速入门系列(2)——深入解析依赖属性
一.引言 感觉最近都颓废了,好久没有学习写博文了,出于负罪感,今天强烈逼迫自己开始更新WPF系列.尽管最近看到一篇WPF技术是否老矣的文章,但是还是不能阻止我系统学习WPF.今天继续分享WPF中一个最 ...
随机推荐
- 【新手引导】MAC如何允许安装任何来源的软件(安装第三方软件/应用)
1 打开系统偏好设置,找到安全性与隐私(第一行第六个) 2 进入安全性与隐私,点击左下角一个锁的按钮,输入自己电脑密码,允许从以下位置下载的应用: 新电脑应该是两个选项 1.APP store 2.A ...
- 使用Buildpacks高效构建Docker镜像
1. 前言 Spring Boot 2.3.0.RELEASE 正式发布了几天了,其中有个新的特性:可以将Spring Boot应用代码直接打包为Docker镜像.这是什么科技?我赶紧去官网查了一番才 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 用AutoMapper搞定对象映射
上一篇文章(https://www.cnblogs.com/meowv/p/12961014.html)集成了定时任务处理框架Hangfire,完成了一个简单的定时任务处理解决方案. 本篇紧接着来玩一 ...
- 5.Linux的启动过程和系统指令
1.Linux的启动过程 作为一台计算机,启动它的第一步是加电自检,也就是给电脑用电然后按电源按钮开机.加电之后的运行步骤:(1)加载bios,然后检查硬盘信息 (2)读取MBR的配置(MBR就是硬盘 ...
- sql注入讲解
1.输入1' 发现数据库报错,原因是我们的输入直接被代入到数据库查询语句里面. 2.有没有办法可以不让他报错呢?可以尝试一下构造正确的数据库语法,使之不报错.比如输入 1 and 1=1 试试 sel ...
- python的map,reduce函数与pandas的apply,filter函数
1. python自带的apply.filter.map函数.reduce函数,很多情况下可以代替for循环: map(func,list),对list的每个元素分别执行func函数操作,显然func ...
- css 图片宽度、居中、倒影
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- webmin RCE漏洞利用及分析
Webmin是目前功能最强大的基于Web的Unix系统管理工具.管理员通过浏览器访问Webmin的各种管理功能并完成相应的管理动作. 利用条件:webmin <= 1.910 原因:官网 Sou ...
- DFA最小化
1.将DFA最小化:教材P65 第9题 2.构造以下文法相应的最小的DFA S→ 0A|1B A→ 1S|1 B→0S|0 3.自上而下语法分析,回溯产生的原因是什么? 文法中,对于某个非终结符号的规 ...
- Linux磁盘与文件系统管理概要
Linux磁盘与文件系统管理 硬盘组成与分区 硬盘组成 圆形的盘片(主要记录数据) 机械手臂与磁头(可读取盘片上的数据) 主轴马达,转动盘片,让机械手臂的磁头在盘片上读取数据 扇区(Sector)为最 ...