В VisualStateGroup
есть что-то фундаментальное, чего я не понимаю. Все, что я прочитал, привело меня к мысли, что они ортогональны. То есть изменение состояния в одной группе не повлияет на другие группы. В самом деле, они были бы довольно бессмысленными, если бы это было не так.
Однако, пытаясь понять какое-то странное поведение, с которым я столкнулся, я собрал простой пример, который показывает, что изменение состояния в одной группе может вызвать анимацию в другой. Я пытаюсь понять, как это может быть.
Все, что я хочу, - это элемент управления на основе ToggleButton
, который будет иметь один вид при переключении (IsChecked == true
), независимо от того, находится ли он в фокусе или, например, над ним мышь.
Во-первых, у меня есть очень простой элемент управления для перехода между пользовательскими состояниями в пользовательской группе:
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
[TemplateVisualState(Name = normalState, GroupName = activationGroupName)]
[TemplateVisualState(Name = hoverState, GroupName = activationGroupName)]
[TemplateVisualState(Name = activatedState, GroupName = activationGroupName)]
public class CustomControl : ToggleButton
{
private const string activationGroupName = "Activation";
private const string normalState = "Normal";
private const string hoverState = "Hover";
private const string activatedState = "Activated";
public CustomControl()
{
this.DefaultStyleKey = typeof(CustomControl);
this.Checked += delegate
{
this.UpdateStates();
};
this.Unchecked += delegate
{
this.UpdateStates();
};
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.UpdateStates();
}
protected override void OnMouseEnter(MouseEventArgs e)
{
base.OnMouseEnter(e);
this.UpdateStates();
}
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
this.UpdateStates();
}
private void UpdateStates()
{
var state = normalState;
if (this.IsChecked.HasValue && this.IsChecked.Value)
{
state = activatedState;
}
else if (this.IsMouseOver)
{
state = hoverState;
}
VisualStateManager.GoToState(this, state, true);
}
}
Во-вторых, у меня есть шаблон для этого элемента управления, который меняет цвет фона в зависимости от текущего состояния:
<Style TargetType="local:CustomControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CustomControl">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Activation">
<VisualStateGroup.Transitions>
<VisualTransition To="Normal" GeneratedDuration="00:00:0.2"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="Hover">
<Storyboard>
<ColorAnimation Duration="00:00:0.2" To="Red" Storyboard.TargetName="grid" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Activated">
<Storyboard>
<ColorAnimation Duration="00:00:0.2" To="Blue" Storyboard.TargetName="grid" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="grid" Background="White">
<TextBlock>ToggleButton that should be white normally, red on hover, and blue when checked</TextBlock>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
По большей части это работает, но когда элемент управления теряет фокус, он возвращается в нормальное состояние.
Я могу обойти это, явно обработав изменения фокуса в моем элементе управления и приняв обновление состояния:
public CustomControl()
{
this.DefaultStyleKey = typeof(CustomControl);
this.Checked += delegate
{
this.UpdateStates();
};
this.Unchecked += delegate
{
this.UpdateStates();
};
// explicitly handle focus changes
this.GotFocus += delegate
{
this.UpdateStates();
};
this.LostFocus += delegate
{
this.UpdateStates();
};
}
Однако для меня нет смысла, почему я должен это делать.
Почему изменение состояния в одном VisualStateGroup
вызывает выполнение анимации, определенной другим? И какой самый простой, самый правильный способ для меня достичь поставленной цели?
Спасибо