C# 元素属性语法和属性语法之间有语义上的区别吗?

C# 元素属性语法和属性语法之间有语义上的区别吗?,c#,.net,wpf,xaml,exception,C#,.net,Wpf,Xaml,Exception,我认为元素属性语法和属性属性语法在语义上没有太大的区别。然而,我发现一定有一些不同 例如,以下示例仅演示了一个简单的触发器: <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Button><Button.Template> <ControlTe

我认为元素属性语法和属性属性语法在语义上没有太大的区别。然而,我发现一定有一些不同

例如,以下示例仅演示了一个简单的触发器:

<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>

那么,元素属性语法和属性属性语法之间隐藏的区别是什么呢?

应该没有区别。我想您刚刚在XAML解析器中发现了一个bug

该框架对Setter、Trigger和Condition有特殊的处理。检查Reflector,它会覆盖值和属性的属性设置器的处理。我认为这是为了使它能够基于属性解析具有不同类型的Value属性。例如,当它看到属性为前景且前景为Brush类型时,它将“Red”解析为笔刷,而不仅仅是字符串

看起来钩子覆盖了触发器中名为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将得到与第二个示例相同的错误,您可以通过设置断点验证从未设置属性:

<Trigger.Property>
    <local:Test>
        <local:Test.Property>IsMouseOver</local:Test.Property>
    </local:Test>
</Trigger.Property>

伊斯穆塞弗
但是,这将起作用,因为该属性未命名为“属性”:


伊斯穆塞弗
这将起作用,因为它使用属性语法:

<Trigger.Property>
    <local:Test Property="IsMouseOver"/>
</Trigger.Property>

如果您真的需要使用元素属性语法,这将为您提供一种解决方法:创建一个MarkupExtension,该扩展的属性类型为DependencyProperty,名称不是“property”,并以ProvideValue的形式返回该属性

<Trigger.Property>
    <local:Test>
        <local:Test.Property2>IsMouseOver</local:Test.Property2>
    </local:Test>
</Trigger.Property>
<Trigger.Property>
    <local:Test Property="IsMouseOver"/>
</Trigger.Property>