[笔记/翻译]WPF的新特性——依赖属性(5)
来源:互联网 发布:虚幻4和unity3d区别 编辑:程序博客网 时间:2024/05/22 03:53
附加属性
附加属性一种特殊的依赖属性形式,它可以被附加到任意对象上。
对于之前的About Dialog示例,如果我们不想让整个Window元素及其子元素都被FontSize和FontStyle影响,而是希望改变它们仅影响位于第二个StackPanel中的OK和Help两个按钮。我们很自然地会想到把它们从Window元素中移动到StackPanel元素中,但这样做是不可以的,因为StackPanel本身并不包含任何与字体相关的属性。此时,我们可以使用定义在TextElement类中的附加属性FontSize和FontStyle来完成相同的任务:
<Window x:Class="Test.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPF揭秘" SizeToContent="WidthAndHeight"
Background="OrangeRed">
<StackPanel>
<Label FontWeight="Bold" FontSize="20" Foreground="White">
WPF揭秘(版本3.0)
</Label>
<Label>(C)2006 SAMS 出版集团</Label>
<Label>已安装的章节:</Label>
<ListBox>
<ListBoxItem>第一章</ListBoxItem>
<ListBoxItem>第二章</ListBoxItem>
</ListBox>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center"
TextElement.FontSize="30" TextElement.FontStyle="Italic">
<Button MinWidth="75" Margin="10">Help</Button>
<Button MinWidth="75" Margin="10">OK</Button>
</StackPanel>
<StatusBar>
<Button>您已经注册了本产品。</Button>
</StatusBar>
</StackPanel>
</Window>
TextElement.FontSize和TextElement.FontStyle必须用在StackPanel元素上,因为它不包含这两个属性。当XAML解析器/编译器遇到这个语法时,需要TextElement(有时被称作“附加属性提供器”)提供静态的SetFontSize和SetFontStyle方法。因此,与上例中第二个StackPanel等价的C#代码为:
StackPanel panel = new StackPanel();
TextElement.SetFontSize(panel, 30);
TextElement.SetFontStyle(panel, FontStyles.Italic);
panel.Orientation = Orientation.Horizontal;
panel.HorizontalAlignment = HorizontalAlignment.Center;
Button helpButton = new Button();
helpButton.MinWidth = 75;
helpButton.Margin = new Thickness(10);
helpButton.Content = "Help";
Button okButton = new Button();
okButton.MinWidth = 75;
okButton.Margin = new Thickness(10);
okButton.Content = "OK";
panel.Children.Add(helpButton);
panel.Children.Add(okButton);
枚举值如FontStyles.Italic、Orientation.Horizontal和HorizontalAlignment.Center可以在XAML中被分别简单表示为Italic、Horizontal和Center,这要感谢.NET中的EnumConverter类型转换器,它可以将任何大小写不敏感的字符串转换为枚举值。
在内部,SetFontSize方法调用了DependencyObject.SetValue方法,后者一般由依赖属性的访问器(accessor)(就是之前说过的按钮的IsDefaultProperty的访问器IsDefault)调用,但此时却是由当前传入的DependencyObject的实例进行调用:
public static void SetFontSize(DependencyObject element, double value)
{
element.SetValue(TextElement.FontSizeProperty, value);
}
相似地,附加属性也定义了调用DependencyObject.GetValue的GetXXX方法:
public static double GetFontSize(DependencyObject element)
{
return (double)element.GetValue(TextElement.FontSizeProperty);
}
附加属性被广泛使用在WPF的布局系统中,相关内容放到以后介绍。
Button等控件继承的FontSize和FontStyle附加属性并不是由它们自己定义的,而是定义在其基类Control中,这十分令人迷惑。实际上,它们真正被定义在看起来与控件并不相关的TextElement类当中。在TextElement类中,包含下面的注册代码:
TextElement.FontSizePropert = DependencyProperty.RegisterAttached(
"FontSize", typeof(double), typeof(TextElement),
new FrameworPropertyMetadata(
SystemFonts.MessageFontSize,
FrameworkPropertyMetadataOptions.Inherits |
FrameworkPropertyMetadataOptions.AffectsRender,
FrameworkPropertyMetadataOptions.AffectsMeasure),
new ValidateValueCallback(TextElement.IsValidFontSize));
与前面讲到的Button.IsDefaultProperty的Register类似,只不过RegisterAttached为附加属性优化了元数据的处理过程。
控件并不注册它们,而是通过调用AddOwner来添加一个已注册了的依赖属性:
Control.FontSizeProperty = TextElement.FontSizeProperty.AddOwner(
typeof(Control), new FrameworkPropertyMetadata(SystemFonts.MessageFontSize,
FrameworkPropertyMetadata.Inherits));
因此,由控件继承所公开的FontSize、FontStyle以及其它字体相关的依赖属性都与TextElement公开的属性完全一样。所幸在多数类中,公开了附加属性的类(比如包含GetXXX和SetXXX)都与定义了一般依赖属性的类相同,这使得许多混乱得以避免。
与Windows Form类似,WPF中的许多类也定义了一个System.Object类型的Tag属性,用以存储任意与当前实例相关的数据。与Tag属性相比,附加属性是为派生自DependencyObject的对象附加自定义数据的一种更加强大、更灵活的机制。附加属性允许为密封类(sealed)的实例添加自定义数据,WPF中有许多这样的做法,常常被忽略。
尽管在XAML中设置附加属性时需要依靠静态的SetXXX方法,但是我们在程序代码中可以直接通过DependencyObject.SetValue方法完成。这意味着我们可以在程序代码中将任何依赖属性作为附加属性。例如,下例将ListBox的IsTextSearchEnabled属性附加给了Button,并为其设置了一个值:
okButton.SetValue(ListBox.IsTextSearchEnabledProperty, true);
尽管这么做没什么意义,而且它确实对Button不起作用,但是我们仍旧可以一种对程序和组件有意义的方式来自由地使用它。
下例展示了一种有趣的元素扩展方式:FrameworkElement的Tag属性是一个依赖属性,因此我们可以把它附加到GeometryModel3D的实力上。
GeometryModel3D model = new GeometryModel3D();
model.SetValue(FrameworkElement.TagProperty, "自定义数据");
- [笔记/翻译]WPF的新特性——依赖属性(5)
- [笔记/简译]WPF的新特性——依赖属性(1)
- [笔记/简译]WPF的新特性——依赖属性(2)
- [笔记/简译]WPF的新特性——依赖属性(3)
- [笔记/简译]WPF的新特性——依赖属性(4)
- [笔记]WPF中的新特性——依赖属性(6)
- [笔记/简译]WPF的新特性——逻辑树和视觉树(上)
- [笔记/简译]WPF的新特性——逻辑树与视觉树(下)
- [笔记/简译]WPF的新特性——路由事件(1)
- WPF学习笔记——理解依赖属性
- WPF(依赖属性)
- (WPF)依赖属性
- (WPF)依赖属性
- WPF注册依赖属性—依赖属性值继承方法
- 继续聊WPF——依赖项属性(1)
- 继续聊WPF——依赖项属性(2)
- 继续聊WPF——依赖项属性(3)
- WPF学习——依赖项属性(1)
- http://www.blogjava.net/beansoft/archive/2007/03/09/102812.html
- eclipse+myeclipse的安装步骤
- 设计模式浅谈
- 联想投资刘二海:创业公司要管好现金避免突然死亡
- 乔布斯在斯坦福的演讲
- [笔记/翻译]WPF的新特性——依赖属性(5)
- API函数快速入门--API函数简介
- API函数快速入门--API函数简介
- linux自动启动shell和init概述
- 每天只需10分钟的减肥
- prototype.js日常应用函数积累
- 发一个自己编的WINDOWS钩子枚举程序
- 技巧(2)- 如何在程序运行时,将datawindow中的text控件字体设为粗体?
- Extjs2.0之横向Radio经典布局