带触发器的继承WPF样式不起作用 [英] Inherited WPF Style with triggers doesn't work

查看:221
本文介绍了带触发器的继承WPF样式不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一种样式可以淡出带有动画的控件:

I have a style that fades out a control with animation:

<Style x:Key="ExpireFadeStyle">
    <Style.Resources>
        <!--Change this in a derived style if required-->
        <sys:Double x:Key="FinalVal">0.25</sys:Double>
    </Style.Resources>
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsExpired}" Value="True">
            <DataTrigger.EnterActions>
                <BeginStoryboard x:Name="ExpireAnimation">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="Opacity"
                                From="1" To="{StaticResource FinalVal}" Duration="0:0:3" />
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
            <DataTrigger.ExitActions>
                <StopStoryboard BeginStoryboardName="ExpireAnimation" />
            </DataTrigger.ExitActions>
        </DataTrigger>
    </Style.Triggers>
</Style>

(IsExpired属性始终存在于应该使用样式的控件的DataContext中.)

(The IsExpired property always exists in the DataContext of the control where the style is supposed to be used.)

当我直接在控件中使用此样式时,一切正常:

When I use this style directly in a control, it all works fine:

<StackPanel Style="{StaticResource ExpireFadeStyle}">
    ...etc

但是当我从这种风格中衍生出来时,就像

But when I derive from this style, just as simple as

<Style x:Key="ExpireTextFadeStyle" BasedOn="{StaticResource ExpireFadeStyle}"/>

...然后在相同控件上以相同方式使用派生样式,则不起作用. (当然是要对其进行一些更改,尤其是FinalVal,但是它必须首先在很小的情况下起作用).

...and then use the derived style on the same control the same way, it doesn't work. (The intention is, of course, to change it a bit, particularly the FinalVal, but it has to work in a trivial case first).

继承的样式本身似乎确实起作用:如果在其中添加一些Setter,则会看到其效果.似乎Triggers没有被继承或根本不起作用.如何解决呢?

The inherited style itself does seem to work: if I add some Setter to it, I see its effect. It just seems that Triggers are not inherited or simply don't work. How to work around it?

推荐答案

这确实是一个好问题.我创建了一个示例测试应用程序来进行检验,而我也遇到了完全相同的问题.在调试模式下,我检查了Style属性的值并且它是正确的(BasedOn设置正确,BasedOn.Triggers包含您的触发器).不过,触发器在需要时不会启动.

That's really a good question. I created an example test application to check this out and I have faced exactly the same problem. In debug mode I checked the value of the Style property and it was correct (BasedOn was set correctly and BasedOn.Triggers contains your Trigger). Nevertheless, the Trigger doesn't fire up when needed.

我找到了一种解决方案,可以解决这个问题,但是它并不是一个完美的解决方案... 我定义了一个附加的依赖项属性,该属性在设置为true时将复制触发器.

I have found a solution that make this work, however it is not a perfect one... I defined an attached dependency property which copies the triggers when is set to true.

public class StyleTriggersInheritanceHelper
{
    public static readonly DependencyProperty AddInheritedTriggersProperty =
        DependencyProperty.RegisterAttached("AddInheritedTriggers", typeof(bool), typeof(FrameworkElement), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnAddInheritedTriggers)));

    private static void OnAddInheritedTriggers(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var b = e.NewValue as bool?;
        if (b.HasValue && b.Value)
        {
            FrameworkElement element = sender as FrameworkElement;
            if(element != null)
            {
                Style style = element.Style;
                if(style != null)
                {
                    Style baseStyle = element.Style.BasedOn;
                    Style newStyle = new Style() { BasedOn = style };
                    if(baseStyle != null)
                    {
                        foreach (var tr in style.Triggers)
                            newStyle.Triggers.Add(tr);
                        foreach (var tr in baseStyle.Triggers)
                            newStyle.Triggers.Add(tr);
                    }
                    element.Style = newStyle;
                }
            }
        } 
    }

    public static bool GetAddInheritedTriggers(DependencyObject obj)
    {
        return (bool)obj.GetValue(AddInheritedTriggersProperty);
    }

    public static void SetAddInheritedTriggers(DependencyObject obj, bool value)
    {
        obj.SetValue(AddInheritedTriggersProperty, value);
    }
}

xaml如下所示:

<local:ExpirdedControl IsExpired="{Binding IsExpired}" Style="{StaticResource InheritedStyle}" x:Name="ExpiredName" local:StyleTriggersInheritanceHelper.AddInheritedTriggers="True"/>

请注意,AddInheritedTriggers附加属性设置为true,然后复制触发器.重要的一件事是您必须在应用样式后设置AddInheritedTriggers,否则它将无法正常工作!

Note that AddInheritedTriggers attached property is set to true and then Triggers are copied. One important thing is that you have to set AddInheritedTriggers after applying the Style, otherwise it wouldn't work!

对我来说,它可行,但是解决方案并不完美,因此,我希望看到一种更好的方法来解决此问题.

For me it works, however the solution is not elegant, so I would like to see a better try of solving this issue.

这篇关于带触发器的继承WPF样式不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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