酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

ToggleSwitchを使ってOn/Offを制御する

Windows Phone Advent Calendar "ひとり" 2011」第7日目です。

引き続き、Windows Phone Toolkitのお話です。標準の設定アプリ等で多く使われているToggleSwitchの使い方についてご紹介します。

ToggleSwitchは、スイッチ部分を右スライドと左スライドでOn/Offの切り替えをするため、画面を左右にスライドさせてページを切り替えるPanoramaやPivotと相性が悪いです。

(おそらくリジェクトはされないレベルだとは思いますが)アプリケーション認定要件に親コンテナ(例:Pivot)でジェスチャー(例:左右フリック)を使用するときは、同じジェスチャーを使用するコントロール(ToggleSwitch)を使うのは推奨されないとあります。

PanoramaやPivot上でOn/Offの切り替えしたい場合は、チェックボックスを使うようにするのが定石のようです。*1 *2

**ToggleSwitchを表示する

Silverlight for Windows Phone Toolkitのアセンブリへの参照追加しておきます。表示させるのは非常に簡単で任意の場所に以下のXAMLを追加します。

|xml| <toolkit:ToggleSwitch Content="コンテント" Header="ヘッダー" /> ||<

実行してみました。簡単ですがヘッダー、コンテント、スイッチ部分が表示されているのが分かります。


全体のXAMLです。

|xml| <phone:PhoneApplicationPage x:Class="ToggleTest.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True">

 <Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock x:Name="ApplicationTitle" Text="SOFTBUILD" Style="{StaticResource PhoneTextNormalStyle}"/>
        <TextBlock x:Name="PageTitle" Text="ToggleSwitch Test" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <toolkit:ToggleSwitch Content="コンテント" Header="ヘッダー" />
    </Grid>
</Grid>

</phone:PhoneApplicationPage> ||<

**Onにされた事を通知するCheckedイベント

RoutedEventArgs型のOriginalSourceプロパティをToggleSwitch型にキャストして、チェックの状態がどうなっているか調べています。チェックが付けられた状態をIsCheckedプロパティから取得しています。

|cs| private void ToggleSwitch_Checked(object sender, RoutedEventArgs e) { var toggleSwitch = e.OriginalSource as ToggleSwitch; if (toggleSwitch == null) { return; }

var isChecked = toggleSwitch.IsChecked;

} ||<

**Offにされた事を通知するUncheckedイベント

senderをToggleSwitch型にキャストして、チェックの状態がどうなっているか状態を取得しています。

|cs| private void ToggleSwitch_Unchecked(object sender, RoutedEventArgs e) { var toggleSwitch = sender as ToggleSwitch; if (toggleSwitch == null) { return; }

var isChecked = toggleSwitch.IsChecked;

} ||<

**データバインディングでOn/Offの状態を管理する

OnとOffの切り替えのイベントが発行されるので、MainPage.xaml.cs内にbool型のクラスプロパティを制御することも出来ますが、数が増えてくると管理が出来なくなってしまうのでデータバインディングしてまとめて管理してしまいましょう。

管理用のViewModelクラスを作成します。

|cs| public class SwitchViewModel : INotifyPropertyChanged {

    private bool CheckedVal;
    public bool Checked {
        get { return CheckedVal; }
        set {
            if (value != CheckedVal) {
                CheckedVal = value;
                NotifyPropertyChanged("Checked");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string propertyName) {
        if (PropertyChanged != null) {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}   

||<

View側でIsCheckedプロパティを変更とViewModel側でのCheckedプロパティの変更を相互に反映するためにバインディングのモードをTwoWayにしておきます。

|xml| <toolkit:ToggleSwitch Content="コンテント" Header="ヘッダー" IsChecked="{Binding Checked, Mode=TwoWay}" /> ||<

LayoutRoot.DataContextに先ほど作成したSwitchViewModel型のインスタンスを設定して終わりです。

|cs| using System.ComponentModel; using System.Windows; using Microsoft.Phone.Controls;

namespace ToggleTest { public partial class MainPage : PhoneApplicationPage {

    SwitchViewModel switchViewModel = new SwitchViewModel();
    public MainPage() {
        InitializeComponent();
        LayoutRoot.DataContext = switchViewModel;
    }
}

} ||<