使用 DataTrigger 时 WPF GoToStateAction 不会触发

发布于 2024-11-10 13:36:35 字数 3938 浏览 0 评论 0原文

请考虑以下代码:

<Window>    
    <Window.Tag>
        <Button x:Name="myButton"/>
    </Window.Tag>

    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState x:Name="VisualState">
                    <Storyboard>
                        <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="canvas">
                            <EasingColorKeyFrame KeyTime="0" Value="Red"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Canvas x:Name="canvas" Background="White">  
            <i:Interaction.Triggers>
                <ei:DataTrigger Value="True">
                    <ei:DataTrigger.Binding>
                        <Binding Path="Equals">
                            <Binding.Source>
                                <local:DependencyObjectComparer X="{x:Reference myButton}" Y="{x:Reference myButton}"/>
                            </Binding.Source>
                        </Binding>
                    </ei:DataTrigger.Binding>
                    <ei:GoToStateAction StateName="VisualState"/>
                </ei:DataTrigger>
                <i:EventTrigger EventName="MouseLeftButtonDown">
                    <ei:GoToStateAction StateName="VisualState"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>          
        </Canvas>
    </Grid>
</Window>

DependencyObjectComparer 确实会比较“X”和“Y”是否相等:

public class EqualityComparer<T> : IEqualityComparer<T>
{
    public EqualityComparer(Func<T, T, bool> comparer)
    {
        Contract.Requires(comparer != null);
        this.m_comparer = comparer;
    }

    public bool Equals(T x, T y)
    {
        return this.m_comparer(x, y);
    }

    public int GetHashCode(T obj)
    {
        return obj.ToString().ToLower().GetHashCode();
    }

    private readonly Func<T, T, bool> m_comparer;
}

public class LazyEqualityComparer<T> : DependencyObject
{
    static LazyEqualityComparer()
    {
        EqualsProperty = DependencyProperty.Register
        (
            "Equals",
            typeof(bool),
            typeof(LazyEqualityComparer<T>),
            null
        );
    }

    public static readonly DependencyProperty EqualsProperty;

    public Func<T, T, bool> Comparer { get; set; }

    public T X
    {
        get { return this.m_x; }
        set
        {
            if (!object.Equals(this.m_x, value))
            {
                this.m_x = value;
                this.OnComperandChanged();
            }
        }
    }

    public T Y
    {
        get { return this.m_y; }
        set
        {
            if (!object.Equals(this.m_y, value))
            {
                this.m_y = value;
                this.OnComperandChanged();
            }
        }
    }

    [Bindable(true)]
    new public bool Equals
    {
        get { return (bool)this.GetValue(EqualsProperty); }
        private set { this.SetValue(EqualsProperty, value); }
    }

    private void OnComperandChanged()
    {
        this.Equals = new EqualityComparer<T>(
            this.Comparer != null ? this.Comparer : (x, y) => x.Equals(y)
        ).Equals(this.X, this.Y);
    }

    private T m_x;
    private T m_y;
}


public class DependencyObjectComparer : LazyEqualityComparer<DependencyObject> { }

当我单击画布时,EventTrigger 会触发,而 DataTrigger 不会,但它确实会返回预期的结果值(真)。这种Action和这种Trigger有什么不兼容的地方吗?

我不知道我在这里做错了什么。感谢您的帮助。

Please consider the following piece of code:

<Window>    
    <Window.Tag>
        <Button x:Name="myButton"/>
    </Window.Tag>

    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState x:Name="VisualState">
                    <Storyboard>
                        <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="canvas">
                            <EasingColorKeyFrame KeyTime="0" Value="Red"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Canvas x:Name="canvas" Background="White">  
            <i:Interaction.Triggers>
                <ei:DataTrigger Value="True">
                    <ei:DataTrigger.Binding>
                        <Binding Path="Equals">
                            <Binding.Source>
                                <local:DependencyObjectComparer X="{x:Reference myButton}" Y="{x:Reference myButton}"/>
                            </Binding.Source>
                        </Binding>
                    </ei:DataTrigger.Binding>
                    <ei:GoToStateAction StateName="VisualState"/>
                </ei:DataTrigger>
                <i:EventTrigger EventName="MouseLeftButtonDown">
                    <ei:GoToStateAction StateName="VisualState"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>          
        </Canvas>
    </Grid>
</Window>

The DependencyObjectComparer does - suprinsingly - compare "X" and "Y" for equality:

public class EqualityComparer<T> : IEqualityComparer<T>
{
    public EqualityComparer(Func<T, T, bool> comparer)
    {
        Contract.Requires(comparer != null);
        this.m_comparer = comparer;
    }

    public bool Equals(T x, T y)
    {
        return this.m_comparer(x, y);
    }

    public int GetHashCode(T obj)
    {
        return obj.ToString().ToLower().GetHashCode();
    }

    private readonly Func<T, T, bool> m_comparer;
}

public class LazyEqualityComparer<T> : DependencyObject
{
    static LazyEqualityComparer()
    {
        EqualsProperty = DependencyProperty.Register
        (
            "Equals",
            typeof(bool),
            typeof(LazyEqualityComparer<T>),
            null
        );
    }

    public static readonly DependencyProperty EqualsProperty;

    public Func<T, T, bool> Comparer { get; set; }

    public T X
    {
        get { return this.m_x; }
        set
        {
            if (!object.Equals(this.m_x, value))
            {
                this.m_x = value;
                this.OnComperandChanged();
            }
        }
    }

    public T Y
    {
        get { return this.m_y; }
        set
        {
            if (!object.Equals(this.m_y, value))
            {
                this.m_y = value;
                this.OnComperandChanged();
            }
        }
    }

    [Bindable(true)]
    new public bool Equals
    {
        get { return (bool)this.GetValue(EqualsProperty); }
        private set { this.SetValue(EqualsProperty, value); }
    }

    private void OnComperandChanged()
    {
        this.Equals = new EqualityComparer<T>(
            this.Comparer != null ? this.Comparer : (x, y) => x.Equals(y)
        ).Equals(this.X, this.Y);
    }

    private T m_x;
    private T m_y;
}


public class DependencyObjectComparer : LazyEqualityComparer<DependencyObject> { }

While the EventTrigger is firing when I'm clicking on the Canvas, the DataTrigger is not, while it does return the expected value (true). Is there any incompatibility between this kind of Action and this kind of Trigger?

I've no idea what I'm doing wrong here. Thank's for any help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

若无相欠,怎会相见 2024-11-17 13:36:35

最后自己找到了一个解决方案:

<Window>    
    <Window.Tag>
        <Button x:Name="myButton"/>
    </Window.Tag>

    <Grid>              
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState x:Name="Default"/>
                <VisualState x:Name="VisualState">
                    <Storyboard>
                        <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="canvas">
                            <EasingColorKeyFrame KeyTime="0" Value="Red"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Canvas x:Name="canvas" Background="White">         
            <i:Interaction.Triggers>                
                <ei:PropertyChangedTrigger Binding="{Binding Tag, ElementName=window}">                 
                    <i:Interaction.Behaviors>
                        <ei:ConditionBehavior>
                            <ei:ConditionalExpression>
                                <ei:ComparisonCondition LeftOperand="{Binding Tag, ElementName=window}" RightOperand="{x:Reference myButton}"/>
                            </ei:ConditionalExpression>
                        </ei:ConditionBehavior>
                    </i:Interaction.Behaviors>
                    <ei:GoToStateAction StateName="VisualState"/>                       
                </ei:PropertyChangedTrigger>
                <ei:PropertyChangedTrigger Binding="{Binding Tag, ElementName=window}">                 
                    <i:Interaction.Behaviors>
                        <ei:ConditionBehavior>
                            <ei:ConditionalExpression>
                                <ei:ComparisonCondition LeftOperand="{Binding Tag, ElementName=window}" RightOperand="{x:Reference myButton}" Operator="NotEqual"/>
                            </ei:ConditionalExpression>
                        </ei:ConditionBehavior>
                    </i:Interaction.Behaviors>
                    <ei:GoToStateAction StateName="Default"/>                       
                </ei:PropertyChangedTrigger>
            </i:Interaction.Triggers>
        </Canvas>
    </Grid>
</Window>

有谁知道是否可以设置 False-State 而无需再次使用更改的运算符编写条件?就像 DataStateBehavior 可以实现的那样。

Finally found a solution by myself:

<Window>    
    <Window.Tag>
        <Button x:Name="myButton"/>
    </Window.Tag>

    <Grid>              
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState x:Name="Default"/>
                <VisualState x:Name="VisualState">
                    <Storyboard>
                        <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="canvas">
                            <EasingColorKeyFrame KeyTime="0" Value="Red"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Canvas x:Name="canvas" Background="White">         
            <i:Interaction.Triggers>                
                <ei:PropertyChangedTrigger Binding="{Binding Tag, ElementName=window}">                 
                    <i:Interaction.Behaviors>
                        <ei:ConditionBehavior>
                            <ei:ConditionalExpression>
                                <ei:ComparisonCondition LeftOperand="{Binding Tag, ElementName=window}" RightOperand="{x:Reference myButton}"/>
                            </ei:ConditionalExpression>
                        </ei:ConditionBehavior>
                    </i:Interaction.Behaviors>
                    <ei:GoToStateAction StateName="VisualState"/>                       
                </ei:PropertyChangedTrigger>
                <ei:PropertyChangedTrigger Binding="{Binding Tag, ElementName=window}">                 
                    <i:Interaction.Behaviors>
                        <ei:ConditionBehavior>
                            <ei:ConditionalExpression>
                                <ei:ComparisonCondition LeftOperand="{Binding Tag, ElementName=window}" RightOperand="{x:Reference myButton}" Operator="NotEqual"/>
                            </ei:ConditionalExpression>
                        </ei:ConditionBehavior>
                    </i:Interaction.Behaviors>
                    <ei:GoToStateAction StateName="Default"/>                       
                </ei:PropertyChangedTrigger>
            </i:Interaction.Triggers>
        </Canvas>
    </Grid>
</Window>

Does anybody know if it's possible to set a False-State without writing the conditions with changed Operator again? Just like that what's possible with the DataStateBehavior.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文