はじめに

データバインドを調査する(その1)」で、簡単ですが、強力なデータバインドの仕組みを見てもらいました。
さて、この強力なデータバインドが楽しくって、いろいろな場面で活用していたのですが、ユーザーコントロールで利用しようとすると、ちょっとハマリます。
その部分を解説します。

ユーザーコントロールを作ってみよう


プロジェクトで右クリックをして、以下のメニューを選択してください。


選択すると、以下の画面が表示されます。
ファイル名を決定して、ユーザーコントロールを作成してください。


チェックボックスを一つ配置してみます。
XAML側にチェックボックスを一つ用意します。
<Grid>
<CheckBox x:Name="chkCheckBox" Content="CheckBox" 
 HorizontalAlignment="Left" Margin="19,21,0,0" VerticalAlignment="Top"
 Width="155" Foreground="#FF040404"/>
</Grid>


プロパティを追加してみます。
public bool? IsChecked 
{
    get { return this.chkCheckBox.IsChecked; }
    set { this.chkCheckBox.IsChecked = value; }
}

データバインドを設定してみる


MainPageに追加してある、チェックボックスにバインド設定をしてみます。
<StackPanel>
<CheckBox x:Name="chkTest01" />
<CheckBox x:Name="chkTest02" " />
<local:MyUserControl
 IsChecked="{Binding IsChecked, ElementName=chkTest01, Mode=TwoWay}"/>
</StackPanel>

プロパティも作成したので、これで動いてくれるかと思いますが・・・
実行させると、エラーが表示されてしまいます。。。

動作が正しく行われるように修正


データバインド出来るようにするには、プロパティの書き方が変わります。
ユーザーコントロールの内容を全部張り付けてみます。
public sealed partial class MyUserControl : UserControl
{
    public MyUserControl()
    {
        this.InitializeComponent();

        chkTest03.Checked += chkTest03_Checked;
        chkTest03.Unchecked += chkTest03_Unchecked;
    }

    void chkTest03_Unchecked(object sender, RoutedEventArgs e)
    {
        this.SetValue(IsCheckedProperty, chkTest03.IsChecked);
    }

    void chkTest03_Checked(object sender, RoutedEventArgs e)
    {
        this.SetValue(IsCheckedProperty, chkTest03.IsChecked);
    }

    public bool IsChecked
    {
        get { return (bool)GetValue(IsCheckedProperty); }
        set { SetValue(IsCheckedProperty, value); }
    }

    public static readonly DependencyProperty IsCheckedProperty =
        DependencyProperty.Register("IsChecked", 
                                    typeof(bool), 
                                    typeof(MyUserControl),
            new PropertyMetadata(false,
            new PropertyChangedCallback(OnIsCheckedChanged)));
        
    private static void OnIsCheckedChanged(DependencyObject d,
                                    DependencyPropertyChangedEventArgs e)
    {
        var myUserControl = d as MyUserControl;
        if (myUserControl != null)
        {
            myUserControl.SetValue(IsCheckedProperty, e.NewValue);
            myUserControl.chkTest03.IsChecked = (bool)e.NewValue;
        }
            
    }
}

上記のように記述してもらって、実行させるとチェックボックスが連動して動作すると思います。

解説

MSDNより
DependencyProperty.Register (String, Type, Type, PropertyMetadata)
プロパティ名、プロパティ型、所有者型、プロパティ メタデータ、依存関係プロパティを登録します。

PropertyMetadata
指定した既定値とコールバックを使用して、PropertyMetadata クラスの新しいインスタンスを初期化します。

DependencyProperty.Register
第一引数は、プロパティ名 ("IsChecked")
第二引数は、プロパティに使う型(bool)
第三引数は、プロパティが所属する型(MyControl)

PropertyMetadata
第一引数は、デフォルト値を設定します。
第二引数は、値が変更されたときのコールバックを設定します。

おわりに

気が付かないと、ちょっと躓くポイントだと思います。
ストアアプリ開発では、ユーザーコントロールの活用は開発効率の面で大きく影響しますので、
ぜひ、活用してみてください。

調査環境

Windows ストア アプリ
VS2012
C#

更新日

2013/06/25:アップ