冷静了一晚,我就当这次学习的过程是在看狗血剧情的武打小说吧:没有垃圾的武术,只有垃圾的武者……

  还有个话儿怎么说来着:你们是用户,不是客户,也就有个使用的权力。搞清楚身份,别叽叽歪歪的!

  没办法,全世界都说好的东西,我也得从善,继续学习。

  从用法的角度来看,附加属性与依赖属性有所不同。

  定义依赖属性,是为了满足绑定技术的要求,实现对象间的数据同步的目的。

  而附加属性,是为了实现其他对象具有我的某些属性这个目的。

  第一次看到附加属性的应用,是在XAML文档中出现的。

  <Window>
    <Grid>
      <Button x:Name = "btn1" Grid.Row = "1"/>
    </Grid>
  </Window>

  Button,本身没有布局关系的属性,外层的Grid了一些布局关系属性,Button只要引用过来,就可以给自己重新定位,多么神奇的实现!

  附加属性的意思是:我定义的特征可以让别人拿去修饰他自己。换个说法,别人拿了我的牲征,作为他的附加属性来描述自己。

  这里,把“我”定义个名称叫做宿主,“别人”叫做订购者,实现一个简单的附加属性的用例。

    class HostObject : DependencyObject
{ public static string GetAttachedText ( DependencyObject obj )
{
return ( string ) obj.GetValue ( AttachedTextProperty );
} public static void SetAttachedText ( DependencyObject obj, string value )
{
obj.SetValue ( AttachedTextProperty, value );
} // 我觉得这种属性应该叫签证,注册的过程就是登记
public static readonly DependencyProperty AttachedTextProperty =
DependencyProperty.RegisterAttached ( "AttachedText", typeof ( string ), typeof ( HostObject )); }

定义宿主

    class Order : DependencyObject
{
}

定义订购者

        public static void TestAttachedProperty ( )
{
//规规矩矩的用法,从宿主存取值
Order a = new Order ( );
HostObject.SetAttachedText ( a, "aaaa" );
Console.WriteLine ( HostObject.GetAttachedText ( a ) ); //再来一次,两个对象各自存取自己的值
Order b = new Order ( );
HostObject.SetAttachedText ( b, "bbbb" );
Console.WriteLine ( HostObject.GetAttachedText ( b ) );
}

测试用例

  可以看到,宿主和订购者的类之间没有任何的关系。

  从表现形式上看,宿主提供GetAttachedText和SetAttachedText方法,允许订购者订购自己的专用寄存器,最终看起来订购者具备一些额外的属性。细看这两个方法的实现过程,其实是由订购者自己来调用GetValue和SetValue方法,达到存/取值的目的,而不是宿主来做这些事儿。

  通过前日的学习,我已知道,附加属性存储值的地方既不在宿主中,也不在订购者中,而是用另外的一个容器统一管理。

  使用附加属性的对象都要求从DependencyObject派生,这样就自带GetValue和SetValue方法,可以从容器里存取数据了。

  宿主给自己包上一层糖衣,实现GetAttachedText和SetAttachedText方法,表现成从宿主对象上,可以存取订购者的附加属性。

  我们也可以从订购者处,存取附加属性

        public static void TestAttachedProperty2 ( )
{
Order c = new Order ( );
c.SetValue ( HostObject.AttachedTextProperty, "cccc" );
string value = ( string ) c.GetValue ( HostObject.AttachedTextProperty );
Console.WriteLine ( value );
}

从订购者存取值

  我可以更放纵一点

        public static void TestAttachedProperty3 ( )
{ DependencyProperty MyAttachedVisa = DependencyProperty.RegisterAttached ( "MyAttachedRegisterName", typeof ( string ), typeof ( SimpleClass ) );
Order d = new Order ( );
d.SetValue ( MyAttachedVisa, "Hello MyAttachedRegister" );
string value2 = ( string ) d.GetValue ( MyAttachedVisa );
Console.WriteLine ( value2 );
}

直接从附加属性存取数据

  看来,只要类是从DependencyObject派生的,它的对象都可以向容器里伸把手。

  回头再想想最前面那个神奇的Button和Grid,如何实现布局的呢?抛开看不到原理的静态快照,用代码来实现。

        public WindowTestAttachedProperty ( )
{
InitializeComponent ( ); Grid grid = new Grid ( ); grid.ColumnDefinitions.Add ( new ColumnDefinition ( ) );
grid.ColumnDefinitions.Add ( new ColumnDefinition ( ) );
grid.ColumnDefinitions.Add ( new ColumnDefinition ( ) ); Button button = new Button ( );
//可以用宿主的静态方法来设置
Grid.SetColumn ( button, );
//也可以用订购者的实例方法来设置
button.SetValue ( Grid.ColumnProperty, ); grid.Children.Add ( button );
this.Content = grid;
}

代码实现附加属性调用

  那个神奇的现象在这里实现:grid.Children.Add ( button );

  布局对象先达好架子,为将来可能来到的子对象定义好区域。每个子对象被加入时,就给子对象分配位置。

  这个逻辑很简单,子对象中与布局相关的附加属性定义好后,在布局对象调用AddChildren方法时,

  这些属性值同样可以被布局对象获取到。那么用这些值去分配位置就好了。

  开辟一个容器,让宿主和订购者都可以存取里面的数据,就是这么一个技巧,被WPF做为核心技术,展示出众多神奇的现象。

  实际上却是要程序员放弃结构设计的原创权力,调用大量似是而非的糖衣,程序员做的事儿只是看上去象那么回事儿而已。

  崇拜它,你就永远也不知道它其实有多么普通。WPF用最白痴的技巧实现了-灵活与自由!

  有人送给WPF一个爱称-我佩服。于我而言,耗费一周的时间,最后发现,我研究的技术居然如此白痴-我喷饭!

WPF学习(四) - 附加属性的更多相关文章

  1. 【WPF学习】第五十四章 关键帧动画

    到目前为止,看到的所有动画都使用线性插值从起点到终点.但如果需要创建具有多个分段的动画和不规则移动的动画.例如,可能希望创建一个动画,快速地将一个元素滑入到视图中,然后慢慢地将它移到正确位置.可通过创 ...

  2. 【WPF学习】第五十章 故事板

    正如上一章介绍,WPF动画通过一组动画类(Animation类)表示.使用少数几个熟悉设置相关信息,如开始值.结束值以及持续时间.这显然使得它们非常适合于XAML.不是很清晰的时:如何为特定的事件和属 ...

  3. 【WPF学习】第五十七章 使用代码创建故事板

    在“[WPF学习]第五十章 故事板”中讨论了如何使用代码创建简单动画,以及如何使用XAML标记构建更复杂的故事板——具有多个动画以及播放控制功能.但有时采用更复杂的故事板例程,并在代码中实现全部复杂功 ...

  4. 命令——WPF学习之深入浅出

    WPF学习之深入浅出话命令   WPF为我们准备了完善的命令系统,你可能会问:“有了路由事件为什么还需要命令系统呢?”.事件的作用是发布.传播一些消息,消息传达到了接收者,事件的指令也就算完成了,至于 ...

  5. Expression Blend学习四控件

    原文:Expression Blend学习四控件 Expression Blend制作自定义按钮 1.从Blend工具箱中添加一个Button,按住shift,将尺寸调整为125*125; 2.右键点 ...

  6. 【WPF学习】第二十六章 Application类——应用程序的生命周期

    在WPF中,应用程序会经历简单的生命周期.在应用程序启动后,将立即创建应用程序对象,在应用程序运行时触发各种应用程序事件,你可以选择监视其中的某些事件.最后,当释放应用程序对象时,应用程序将结束. 一 ...

  7. 【WPF学习】第五十三章 动画类型回顾

    创建动画面临的第一个挑战是为动画选择正确的属性.期望的结果(例如,在窗口中移动元素)与需要使用的属性(在这种情况下是Canvas.Left和Canvas.Top属性)之间的关系并不总是很直观.下面是一 ...

  8. WPF学习开发客户端软件-任务助手(下 2015年2月4日代码更新)

    时光如梭,距离第一次写的 WPF学习开发客户端软件-任务助手(已上传源码)  已有三个多月,期间我断断续续地对该项目做了优化.完善等等工作,现在重新向大家介绍一下,希望各位可以使用,本软件以实用性为主 ...

  9. WPF学习05:2D绘图 使用Transform进行控件变形

    在WPF学习04:2D绘图 使用Shape绘基本图形中,我们了解了如何绘制基本的图形. 这一次,我们进一步,研究如何将图形变形. 例子 一个三角形,经Transform形成组合图形: XAML代码: ...

  10. TweenMax动画库学习(四)

    目录            TweenMax动画库学习(一)            TweenMax动画库学习(二)            TweenMax动画库学习(三)            Tw ...

随机推荐

  1. 【转】Docker基础

    一.简介 Docker是一个开源的应用容器引擎,使用Go语言开发,基于Linux内核的CGroup.Namespace.Union FS等技术实现的一种系统级虚拟化技术. 特性 更高效的利用系统资源: ...

  2. 微信开发中的序列化json问题..

    微信开发平台: https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list& ...

  3. .NET Core 开发:永远的Hello Word

    从.NET Core发布到现在已经很长一段时间了,园子里的各路大神也和它打的火热,本着与时俱进,啥火学啥的原则,我也开始了我的.NET Core学习之旅. 简介 .NET从2002年发行到现在,从呱呱 ...

  4. Centos7 minimal 系列之桥接模式联网(二)

    一.桥接模式联网 之前用NAT模式连接网络,Centos是可以上网,而且Centos可以ping通主机,但是主机ping不通虚拟机.后来发现Nat模式只能由内而外. 1.1设置虚拟机的网络适配器 1. ...

  5. Vue运行npm run dev 时修改端口

    进入项目文件的config文件夹E:\myapp\myproject\config,找到index.js,修改里面的8080端口,改成8088(确定不被别的程序使用的都可以)

  6. js 手机号码简单正则校验

    现在手机号码的号段有如下几种,包括17年新发出的三个(166,199,198)号段. 在一些项目注册登录或者其他中,涉及到手机号进行一个简单的有效验证,在前端先进行一个简单的检验: 判断字符串是否符合 ...

  7. FrameLsyout

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_ ...

  8. poj2406 Power Strings (kmp 求最小循环字串)

    Power Strings   Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 47748   Accepted: 19902 ...

  9. Day 01 计算机编程基础

    1.编程语言是什么? 编程语言是人与计算机交流的介质 2.什么是编程? 用编程语言写出一个个文件,这堆文件会达到一个目的 3.编程有什么用? 让计算机帮助我们干活,从而解放人类劳动力 4.计算机组成原 ...

  10. 嵌入式平台选择:树莓派 or BeagleBone Black(BBB)

    原文链接: Michael Leonard 翻译: 极客范- 小道空空 译文链接: http://www.geekfan.net/5246/ 嵌入式平台选择:树莓派 or BeagleBone Bla ...