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