我认为元素属性语法和属性属性语法没有很大的语义差异。但是,我发现必须有一些区别。
E.g。以下示例仅演示了一个简单的触发器:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Button><Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock x:Name="hello" Text="Hello" />
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" TargetName="hello"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template></Button>
</Page>
但是,如果我对触发器的属性Property
使用了元素属性语法,则会抛出一个异常,说明了setter! (不是触发器)需要属性和值。
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Button><Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock x:Name="hello" Text="Hello" />
<ControlTemplate.Triggers>
<Trigger Value="True">
<Trigger.Property>IsMouseOver</Trigger.Property>
<Setter Property="Foreground" Value="Red" TargetName="hello"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template></Button>
</Page>
那么,元素属性语法和属性属性语法之间的隐藏区别是什么?
答案 0 :(得分:2)
应该没有区别。我想你刚刚在XAML解析器中发现了一个错误。
框架对Setter,Trigger和Condition有特殊处理。使用Reflector检出Trigger.ReceiveTypeConverter,它会覆盖Value和Property属性的属性设置器的处理。我认为这是因为它可以使用基于Property属性的不同类型解析Value属性。例如,当它看到Property是Foreground并且Foreground是Brush类型时,它将“Red”解析为Brush而不仅仅是String。
看起来该钩子会覆盖Trigger中名为Value或Property的所有属性集,但它不能正确处理元素属性语法。要查看效果,请尝试创建如下标记扩展名:
public class Test
: MarkupExtension
{
public DependencyProperty Property { get; set; }
public DependencyProperty Property2 { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
return Property ?? Property2;
}
}
以下XAML将获得与第二个示例相同的错误,您可以通过设置断点来验证从未设置Property:
<Trigger.Property>
<local:Test>
<local:Test.Property>IsMouseOver</local:Test.Property>
</local:Test>
</Trigger.Property>
但是,这样可行,因为该属性未命名为“Property”:
<Trigger.Property>
<local:Test>
<local:Test.Property2>IsMouseOver</local:Test.Property2>
</local:Test>
</Trigger.Property>
这样可行,因为它使用了属性语法:
<Trigger.Property>
<local:Test Property="IsMouseOver"/>
</Trigger.Property>
如果您确实需要使用element属性语法,那么将为您提供一种解决方法:创建一个MarkupExtension,其属性类型为DependencyProperty,而不是“Property”,并在ProvideValue中返回。