WPF中的Dependency Property(3)
在这一个Post中,我们将重点关注Dependency Property的属性值继承。
属性值继承指的是属性值自顶向下沿着元素树传递,从下面的示例中,我们很快就能理解什么是属性值继承。
<Window x:Class="Demo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ResizeMode="NoResize"
Title="Window1" Height="300" Width="300" FontSize="20" FontStyle="Italic">
<StackPanel>
<Label Content="I'm a Label!"/>
<Button Content="I'm a Button!"/>
<StatusBar>I'm a StatusBar!</StatusBar>
</StackPanel>
</Window>
Window中设置了FontSize="20"和FontStyle="Italic",Label和Button没有设置FontSize和FontStyle,但运行起来后可以看到,它们同样拥有了和Window一样的FontSize和FontStyle,这就是属性值继承,即Label和Button沿着元素树从Window那里继承了部分属性值。
有趣的是,StackPanel根本连FontSize和FontStyle都没有,怎么继承?显然,将FontSize和FontStyle借由元素树来传递的做法,比我们想像更精细,而不是使用简单的“父传子”机制。尽管StackPanel没有FontSize和FontStyle,依然可以让孩子们获得需要被继承的属性值。
如果我们显式的去设定Button或者Label的FontSize和FontStyle,那么,我们可以看到,它们将以自己设定的方式去显示,而不再从元素树中继承了,这是为什么呢?这是因为,如果未设定属性值,它们将以默认值显示;而从元素树中继承属性值的优先权比默认值要高,而“对元素本身的设定”具有最高的优先权。关于这其中的优先权,我们将在下一个Post中讲解。
另外,我们会发现一个问题,为什么StatusBar未设定FontSize和FontStyle,却不从Window那里继承属性值呢?
属性值的继承行为是由以下两种因素决定的:
1) 并不是每个Dependency Property都参与属性值继承(从内部来讲,只有在Register Dependency Property时设定了“metadata.Inherits = true”的Dependency Property才能有继承权限);
2) 有其他优先权更高的源进行了属性值设定;
因此,StatusBar(还有Menu、Tooltip)控件满足了第二个因素才没有从Window那里继承属性值。它是从桌面的主题样式那里获得了属性值,而从桌面的主题样式处获取要比一般的属性值继承的优先权高。这样做的好处是用户可以从控制面板中控制它们的字体,从而让画面都具有一样的风格,对于用户来说很熟悉。
像StatusBar控件,它会阻止继承继续沿着元素树向下传递。例如,如果我们将另一个Button作为StatusBar控件的子元素,它的FontSize和FontStyle将是从桌面的主题样式那里获得的值,而不能从Window那里继承属性值(被StatusBar控件阻止了或者“吞噬”了)。
<StatusBar>
<Button Content="Haha"/>
</StatusBar>