附加属性

书名:WPF专业编程指南
作者:李应保
出版社:电子工业出版社
出版时间:2010-01
ISBN:9787121100116


一、附加属性

  • 附加属性(Attached Property)其实是相关属性的另外一种形式。
    所有从DependencyObject类中派生出来的类,都可以使用附加属性。

二、引入附加属性的原因

  • 为什么要引入附加属性呢?
    可以看这样一个例子:若有一些图形,比如说矩形,要在视窗上显示出来。
    若使用Canvas排版,那么要告诉Canvas该矩形的左上角坐标。
    一种实现方式是定义一个基类,其中含有x,y坐标,然后把具体的图形类从该基类中派生出来,这样所有的图形在Canvas上的位置就确定了。
    然而,这种解决方案,在WPF中会行不通:WPF支持多种排版。
    比如说,同样的图形元素,现在要改在Grid上显示了,这时,就不能使用左上角x,y坐标,而要指出图形在Grid中的行列号。
    又如,同样的图形要在DockPanel中显示时,所要给出的居然是Top、Left、Right或Bottom这样的相对位置。显然,由于WPF排版的多样性,过去所用的解决问题的方法已经不够用了。

三、解决办法

  • WPF引入了附加属性来解决这个问题:图形元素,比如矩形,就不需要预先说明它们在窗口内的位置,当要在某个特定的排版环境中显示时,可以把排版类的某些相关属性引入进来,从而确定自己在窗口中的位置。

  • 在Grid中显示矩形的例子如下:

  <Window x:Class="Yingbao.Chapter4.AttachedPropertyExample"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Yingbao.Chapter4" Height="300" Width="300">
    <Grid>
    <Grid.RowDefinitions>
      <RowDefinition  Height ="*"/>
      <RowDefinition  Height ="2*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width ="*"/>
      <ColumnDefinition Width ="2*"/>
    </Grid.ColumnDefinitions>
    <Rectangle Stroke ="Aqua" Fill ="Brown " Grid.Column ="0"
          Grid.Row ="0"/>
    <Rectangle Stroke ="Blue" Fill ="Yellow " Grid.Column ="1"
          Grid.Row ="0"/>
    <Rectangle Stroke ="Aqua" Fill ="Brown " Grid.Column ="1"
          Grid.Row ="1"/>
    <Rectangle Stroke ="Blue" Fill ="Yellow " Grid.Column ="0"
          Grid.Row ="1"/>
    </Grid>
  </Window>
  • 本例定义了一个2行2列的Grid,用4个矩形填充这4个网格;
    每个矩形在Grid中的位置,是由Grid.Column和Grid.Row确定的。
    显然,这里的Grid.Column和Grid.Row不是矩形的属性,而是Grid的属性。
    为什么可以把Grid的属性用到矩形Rectangle中来呢?
    难道WPF有什么魔法不成?
    在Grid中显示的矩形如图4-5所示。


    图4-5 在Grid中显示矩形
  • 问题的关键在于Rectangle类具有DependencyObject作为它的基类,图4-6是矩形Rectangle类在WPF中的完整类继承树,由图4-6可见,DependencyObject是其中的一个基类,换句话说,Rectangle是DependencyObject(这是UML的通常表述)。


    图4-6 WPF中矩形(Rectangle)的继承树
  • 当我们在XAML中使用下面的语句时:

  <Rectangle Stroke ="Aqua" Fill ="Brown " Grid.Column ="0" Grid.Row
          ="0"/>
  • 设置Grid.Column=“0”,实际上调用的是DependencyObject中的(Grid.Column, “0”)方法。
    类似地,要读取附加属性的值,可以调用DependencyObject中的GetValue方法。
    笔者认为DependencyObject中应该有一个维护相关属性和值之间的哈希表。
    由此可见,要把相关属性引入到某个类中,这个类必须是DependencyObject,这一点非常重要。

  • 其次,如要使相关属性能被引入到DependencyObject类中,则一定要在注册该相关属性时。注册相关属性为附加属性的方法是调用DependencyProperty类中的RegisterAttached方法。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容