为什么某些属性需要在样式中定义默认值才能使DataTrigger生效? [英] Why do some properties need a default defined in the style before a DataTrigger takes effect?

查看:58
本文介绍了为什么某些属性需要在样式中定义默认值才能使DataTrigger生效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么某些依赖项属性需要在样式中具有默认的设置器,然后触发的设置器才会生效?

Why is it that some dependency properties need to have a default setter in the style before the triggered setters will take effect?

例如,

<ContentControl>

    <ContentControl.Resources>
        <DataTemplate x:Key="DefaultTemplate">
            <TextBlock Text="Default Template" />
        </DataTemplate>
        <DataTemplate x:Key="MouseOverTemplate">
            <TextBlock Text="MouseOver Template" />
        </DataTemplate>
    </ContentControl.Resources>

    <ContentControl.Style>
        <Style TargetType="{x:Type ContentControl}">

            <!-- Triggered setter will work without this default setter -->
            <!--<Setter Property="ContentTemplate" 
                        Value="{StaticResource DefaultTemplate}" />-->

            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="ContentTemplate" 
                            Value="{StaticResource MouseOverTemplate}" />
                </Trigger>
            </Style.Triggers>

        </Style>
    </ContentControl.Style>

</ContentControl>

我在某处看到了很好的解释,但我不记得在哪里。我记得它与 WPF应用依赖项属性值的顺序有关,但我不记得详细信息,或者为什么有些属性需要在触发器生效之前定义默认属性,而另一些却没有。

I saw a good explanation of it somewhere, but I can't remember where. I recall it had something to do with the order that WPF applies dependency property values, but I can't remember the details, or why some properties need the default defined before triggers will take effect, while others do not.

推荐答案

如果您的第一个 Style 无法正常工作,除非您的 ContentControl 定义如下,否则我会感到非常惊讶:

I would be very surprised if your first Style does not work, unless your ContentControl is defined like:

<ContentControl ContentTemplate="{StaticResource DefaultTemplate}" />

如果是这样,那么它将与值优先级有关。在您的链接中,像我的示例中那样的设置将位于#3。因此,唯一可以覆盖它的是动画或值是否被强制。 样式 ControlTemplate (如果有)都不能更改 ContentControl.ContentTemplate 属性。

If so, then it would have to do with value precedence. From your link, setting like in my example would be at #3. So the only thing that could override it would be an animation or if the value were coerced. Neither the Style or the ControlTemplate (if any) could change the ContentControl.ContentTemplate property.

使用第二种样式,您可以定义 ContentControl 就像这样:

With your second Style, you could define your ContentControl like so:

<ContentControl />

在这种情况下, Setter DefaultTemplate 位于#8,因此触发器可以覆盖它(就像它们位于#6)。

In this case, the Setter for DefaultTemplate is at #8 so the triggers can override it (as they are at #6).

再次假设,您拥有的

<ContentControl ContentTemplate="{StaticResource DefaultTemplate}" />

然后可以覆盖 DataTemplate ControlTemplate 中使用,但不能更改 ContentControl.ContentTemplate 的值。像这样:

Then it is possible to override the DataTemplate used in the ControlTemplate, but you cannot change the ContentControl.ContentTemplate's value. Something like:

<Style TargetType="{x:Type ContentControl}">
    <Setter Property="ControlTemplate">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ContentControl}">
                <ContentPresenter x:Name="presenter" />
                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding SomeProperty}" Value="A">
                        <Setter TargetName="presenter" Property="ContentTemplate" Value="{StaticResource TemplateA}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding SomeProperty}" Value="B">
                        <Setter TargetName="presenter" Property="ContentTemplate" Value="{StaticResource TemplateB}" />
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

在这里,我们切换 DataTemplate ContentPresenter,因此它有效地忽略了 ContentControl.ContentTemplate 属性。

Here, we switch the DataTemplate used by the ContentPresenter so it effectively ignores the ContentControl.ContentTemplate property.

不过,根据您的更新,鼠标在上方。 ContentControl尚未呈现任何内容(甚至不是透明像素),因此不会收到任何鼠标事件。您可以执行以下操作来更正它:

Based on your updates though, there is nothing for the mouse to be "over". The ContentControl has not rendered anything (not even a transparent pixel), so it would not receive any mouse events. You can do something like this to correct it:

<Style TargetType="{x:Type ContentControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ContentControl}">
                <Border Background="{TemplateBinding Background}">
                    <ContentPresenter />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="ContentTemplate" Value="{StaticResource MouseOverTemplate}" />
        </Trigger>
    </Style.Triggers>
</Style>

然后您需要在ContentControl上设置Background = Transparent。

And you'd need to set Background="Transparent" on the ContentControl.

这篇关于为什么某些属性需要在样式中定义默认值才能使DataTrigger生效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆