c# - 元素属性语法和属性属性语法在语义上有区别吗?

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

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

最佳答案

应该没有区别。我认为您刚刚在 XAML 解析器中发现了一个错误。

框架对 Setter、Trigger 和 Condition 有特殊处理。查看Trigger.ReceiveTypeConverter使用 Reflector,它会覆盖 Value 和 Property 属性的属性 setter 的处理。我认为这是为了它可以根据 Property 属性解析具有不同类型的 Value 属性。例如,当它看到 Property 是 Foreground 并且 Foreground 是 Brush 类型时,它会将“Red”解析为 Brush 而不仅仅是 String。

看起来该 Hook 覆盖了触发器中所有名为 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>

但是,这会起作用,因为该属性未命名为“Property”:

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

这会起作用,因为它使用属性语法:

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

如果您确实需要使用元素属性语法,这将为您提供一个解决方法:创建一个 MarkupExtension,它具有 DependencyProperty 类型的属性,名称不是“Property”,然后在 ProvideValue 中返回它。

关于c# - 元素属性语法和属性属性语法在语义上有区别吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3277375/

相关文章:

c# - WPF 用户控件 - 双向绑定(bind)不起作用

c# - WPF:MVVM - 如果命令为空则禁用按钮

wpf - GetPositionAtOffset 仅对文本等效?

c# - 共享对象和线程

c# - 如何在 C# 中访问 Outlook 电子邮件附件而不将其保存到新位置?

.net - 为什么 .NET 4.5 中没有 CallerTypeNameAttribute?

.net - 类似控制台的文本控件?

c# - 文档光标的路径是什么?

c# - 为什么这个 c# 片段是合法的?

c# - 图片标题总是出现。单击按钮后如何使其消失或隐藏