かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Windows 10 TPのVisualStateManagerのStateTriggerを自作するには

参考:とてもいい仕事してるGitHubのページ。

github.com

ほぼ写経してる感じです。

StateTriggerの作り方

Windows.UI.Xaml.StateTriggerBaseを継承して作ります。特に実装しないといけないメソッド等はなくて、そのStateTriggerが条件を満たす状態になったときにSetTriggerValueにTrueを設定して、条件を満たさない時にはFalseを設定してやるようにするだけでOKです。

ValueプロパティがTrueの時に条件を満たすIsTrueStateTriggerと、その反対のIsFalseStateTriggerのコードは以下のような感じになります。

public class IsTrueStateTrigger : StateTriggerBase
{
    public bool Value
    {
        get { return (bool)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(bool), typeof(IsTrueStateTrigger), new PropertyMetadata(false, ValueChanged));

    private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((IsTrueStateTrigger)d).UpdateState((bool)e.NewValue);
    }

    private void UpdateState(bool value)
    {
        this.SetTriggerValue(value);
    }
}

public class IsFalseStateTrigger : StateTriggerBase
{
    public bool Value
    {
        get { return (bool)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(bool), typeof(IsFalseStateTrigger), new PropertyMetadata(true, ValueChanged));

    private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((IsFalseStateTrigger)d).UpdateState((bool)e.NewValue);
    }

    private void UpdateState(bool value)
    {
        this.SetTriggerValue(!value);
    }
}

使い方は、VisualStateのTriggersに設定して使います。

<Page
    x:Class="App25.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App25"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="ToggleStateGroup">
                <VisualState x:Name="TrueState">
                    <VisualState.StateTriggers>
                        <local:IsTrueStateTrigger Value="{Binding IsChecked, ElementName=ToggleButtonState}" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="TextBlockMessage.Text" Value="True state" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="FalseState">
                    <VisualState.StateTriggers>
                        <local:IsFalseStateTrigger Value="{Binding IsChecked, ElementName=ToggleButtonState}" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="TextBlockMessage.Text" Value="False state" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        
        <TextBlock x:Name="TextBlockMessage"
                   Style="{StaticResource HeaderTextBlockStyle}"
                   Text="こんにちは世界" />
        
        <ToggleButton x:Name="ToggleButtonState"
                      Content="Checked"
                      RelativePanel.Below="TextBlockMessage"
                      IsChecked="False"/>
    </RelativePanel>
</Page>

実行するとToggleButtonのチェック状態に応じてテキストが切り替わることが確認できます。とても簡単ですね。

f:id:okazuki:20150419154708p:plain

f:id:okazuki:20150419154733p:plain