Is there any semantical difference between element property syntax and atrribute property syntax?

﹥>﹥吖頭↗ 提交于 2019-12-23 19:39:01

问题


I thought that element property syntax and attribute property syntax have no big semantical difference. However, I found that there must be some difference.

E.g. The following example just demonstrates a simple trigger:

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

However, if I used a element property syntax for property Property of trigger, it throws an exception saying that setter! (not trigger) requires both property and value.

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

So, what is the hidden difference between element property syntax and attribute property syntax?


回答1:


There shouldn't be a difference. I think you just found a bug in the XAML parser.

The framework has special handling for Setter, Trigger, and Condition. Check out Trigger.ReceiveTypeConverter with Reflector, which overrides the handling of property setters for the Value and Property properties. I think this is so that it can parse the Value property with a different type based on the Property property. For example, it parses "Red" as a Brush rather than just a String when it sees the Property is Foreground and that Foreground is of type Brush.

It looks like that hook overrides all sets of properties named Value or Property within a Trigger, but that it doesn't correctly handle the element property syntax. To see the effect, try creating a markup extension like this:

public class Test
    : MarkupExtension
{
    public DependencyProperty Property { get; set; }
    public DependencyProperty Property2 { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return Property ?? Property2;
    }
}

The following XAML will get the same error as your second example, and you can verify by setting a breakpoint that Property is never set:

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

However, this will work, because the property is not named "Property":

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

And this will work, because it uses the attribute syntax:

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

If you really need to use the element property syntax, that will give you a workaround: create a MarkupExtension that has a Property of type DependencyProperty named something other than "Property", and return that in ProvideValue.



来源:https://stackoverflow.com/questions/3277375/is-there-any-semantical-difference-between-element-property-syntax-and-atrribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!