WPF的Attached属性——出自《IT168》

本篇,我们再继续看一种特殊的 Dependency 属性: Attached 属性。 Attached 属性可以非常高效地 Attach 到其他的对象中。
我们仍然用前面的一个简单 XAML 代码为例:

<Window> <StackPanel> <Label>LabelText</Lable> </StackPanel> </Window>

    现在,如果需要对 StackPanel 及其子元素设置字体大小,应该如何做呢?在 Window 元素中,它有一个属性 FontSize ,可以直接设置。但是, StackPanel 自己本身并没有 FontSize 这样的属性。这就该 Attached 属性出场了。这里我们需要用定义在 TextElement 元素中的 Attached 属性 FontSize 来设置 StackPanel 的字体。

 

<Window> <StackPanel TextElement.FontSize=”30”> <Label>LabelText</Lable> </StackPanel> </Window>

    这样, StackPanel 的子元素就能通过属性值继承得到新的 FontSize 属性。对于这样的 XAML 代码, XAML 编译器或者解析器看到这种语法 时,就要求 TextElement (有时也称为 Attached 属性提供者)有相应的静态方法 SetFontSize 来设置对应的属性值。因此,上面的 Attached 属性设置代码,可以如下用 C# 实现:

 

StackPanel panel = new StackPanel(); TextElement.SetFontSize(panel, 30);

    从这里的代码可以看出, Attached 属性并不神秘。只是调用方法把元素和不相关的属性关联起来。而 SetFontSize 实现也比较简单。 它只是调用 Dependency 属性访问函数所调用的 DependencyObject.SetValue 方法。注意调用的对象是传入的 DependencyObject ,而不是当前的实例:

 

public static void SetFontSize(DependencyObject element, double value) { element.SetValue(TextElement.FontSizeProperty, value); }

    同样地, Attached 属性也定义了对应的 GetXXX 函数。它调用的 DependencyObject.GetValue 方法:

 

public static double GetFontSize(DependencyObject element) { return (double)element.GetValue(TextElement.FontSizeProperty); }

   与普通的 Dependency 属性一样,这些 GetXXX SetXXX 方法除了实现对 GetValue SetValue 的调用,不能做任何其他额外的工作。

   
其实,在 WPF 应用中, Attached 属性更多的用来控制 UI 的布局。除了前面的 StackPanel ,还有 Grid 等等。

   
补充说明:上面的代码还有一个问题需要说明。我们设置 StackPanel 的字体属性时用的是 TextElement 元素。为什么不用其他的元素 Control Button 呢?

   
这个问题的关键之处在于 Dependency 属性的注册方法。我曾在 Dependency 属性 [1] 做过简单的说明。我们看看 Element FontSizeProperty 属性的注册代码:

 

TextElement.FontSizeProperty = DependencyProperty.RegisterAttached( “FontSize”, typeof(double), typeof(TextElement), new FrameworkPropertyMetadata( SystemFonts.MessageFontSize, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure), new ValidateValueCallback(TextElement.IsValidFontSize));

    这里与我们前面的 IsDefault 属性类似,只是 RisterAttached 方法优化了 Attached 属性需要的属性元数据的处理过程。

   
另一方面, Control FontSize 属性是在 TextElement 元素已经注册的属性之上调用 AddOwner 方法,获取一个完全相同的实例引用:

 

Control.FontSizeProperty = TextElement.FontSizeProperty.AddOwner( typeof(Control), new FrameworkPropertyMetadata(SystemFonts.MessageFontSize, FrameworkPropertyMetadataOptions.Inherits));

   所以,在实现 Attached 属性时我们使用的是 TextElement ,而不是 Control 等等。

你可能感兴趣的:(优化,工作,C#,button,WPF,编译器)