VisualStateGroup
私が理解していない sについての基本的なことがあります。私が読んだすべてのことから、それらが直交していると信じるようになりました。つまり、あるグループの状態が変化しても、他のグループには影響しません。実際、そうでないと意味がありません。
ただし、私が遭遇したいくつかの奇妙な動作を理解しようとして、あるグループの状態変化が別のグループのアニメーションをトリガーできることを示す簡単な例をまとめました。私はこれがどのようにできるかを理解しようとしています。
私が望むのは、たとえば、フォーカスがあるかどうか、またはマウスがその上にあるかどうかに関係なく、ToggleButton
トグル ( ) されたときに 1 つの外観を持つベースのコントロールだけです。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();
};
}
しかし、なぜ私がこれをしなければならないのか、私には意味がありません。
1 つの状態が変化するとVisualStateGroup
、別のアニメーションで定義されたアニメーションが実行されるのはなぜですか? そして、私が述べた目標を達成するための最も簡単で最も正しい方法は何ですか?
ありがとう