WPF GoToStateAction не запускается при использовании DataTrigger - PullRequest
1 голос
/ 30 мая 2011

Пожалуйста, обратите внимание на следующий фрагмент кода:

<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срабатывает, когда я нажимаю на Canvas, а DataTrigger - нет, в то время как он возвращает ожидаемое значение (true).Есть ли какая-либо несовместимость между этим типом действия и этим типом триггера?

Я понятия не имею, что я делаю здесь неправильно.Спасибо за любую помощь.

1 Ответ

1 голос
/ 30 мая 2011

Наконец-то нашел решение сам:

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

...