WPF 依存プロパティの作り方

WPFの依存プロパティの作成方法のサンプルです。

## サンプルプログラム

テキストを表示するUserControlを作成する。
表示するテキストはTitleプロパティで指定する。
このTitleプロパティは依存プロパティとして実装する。

```csharp:DependencyPropertyTestControl.xaml.cs

// UserControlのコードビハインド
public partial class DependencyPropertyTestControl : UserControl
{
    // 1. 依存プロパティの作成
    public static readonly DependencyProperty TitleProperty =
        DependencyProperty.Register("Title", 
                                    typeof(string),
                                    typeof(DependencyPropertyTestControl),
                                    new FrameworkPropertyMetadata("Title", new PropertyChangedCallback(OnTitleChanged)));

    // 2. CLI用プロパティを提供するラッパー
    public string Title
    {
        get { return (string)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }

    // 3. 依存プロパティが変更されたとき呼ばれるコールバック関数の定義
    private static void OnTitleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        // オブジェクトを取得して処理する
        DependencyPropertyTestControl ctrl = obj as DependencyPropertyTestControl;
        if (ctrl != null)
        {
            ctrl.TitleTextBlock.Text = ctrl.Title;
        }
    }

    // コンストラクタ
    public DependencyPropertyTestControl()
    {
        InitializeComponent();
        Title = "Set Title Property";
    }
}
```

```xml:DependencyPropertyTestControl.xaml
<UserControl x:Class="DependencPropertyTest.DependencyPropertyTestControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="50" d:DesignWidth="300">
    <Grid>
        <TextBlock Name="TitleTextBlock" Text="Set Title Property" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18" FontWeight="Bold" />
    </Grid>
</UserControl>
```

```xml:MainWindow.xaml
<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DependencPropertyTest" 
        x:Class="DependencPropertyTest.MainWindow"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <!-- ViewModelをリソースとして生成 -->
        <local:MainWindowViewModel x:Key="ViewModel" />
    </Window.Resources>
    <Grid DataContext="{StaticResource ViewModel}">
    　　<!-- 作成したサンプルのUserControl　：　依存プロパティにViewModelのプロパティをバインドする -->
        <local:DependencyPropertyTestControl Title="{Binding Title}" />
    </Grid>
</Window>
```

```csharp:MainWindowViewModel.cs
// ViewModel
class MainWindowViewModel : WindowViewModelBase
{
    // データバインディング用のプロパティ
    public string Title
    {
        get { return GetDataBindItem<string>("Title").Value; }
        private set { GetDataBindItem<string>("Title").Value = value; }
    }

    // コンストラクタ
    public MainWindowViewModel()
    {
        CreateDataBindItem<string>("Title", "Depedency Property Test");
    }
}
```

## コードの説明

### 1. 依存プロパティの作成

DependencyPropertyクラスの静的メソッド`DependencyProperty.Register`を呼び出して、依存プロパティの生成と登録を行います。
生成されたインスタンスは、`public static readonly DependencyProperty`なメンバー変数に保持しておきます。この時、変数の名称は「依存プロパティ名」+「Property」でなければいけません。

`DependencyProperty.Register`には、いくつかのオーバーロードが存在しますが、このサンプルではプロパティの名称、プロパティの型、プロパティを所有するクラスの型の他にプロパティの付随情報を保持するFrameworkPropertyMetadataクラスのインスタンスにプロパティの初期値とプロパティの値が変更された場合に呼び出されるコールバック関数を指定して渡しています。

```csharp
public static readonly DependencyProperty TitleProperty =
    DependencyProperty.Register("Title",                                 // プロパティ名
                                typeof(string),                          // プロパティの型
                                typeof(DependencyPropertyTestControl),   // プロパティを所有するクラス
                                new FrameworkPropertyMetadata("Title", new PropertyChangedCallback(OnTitleChanged))); // メタ情報
```

[MSDN:DependencyProperty.Register メソッド ](http://msdn.microsoft.com/ja-jp/library/ms597502\(v=vs.110\).aspx)

### 2. コードからアクセスするためのプロパティの作成

コードから依存プロパティにアクセスするには、`DependencyObject.GetValue()`、`DependencyObject.SetValue()`を利用しないといけないので、通常のプロパティと同様にアクセスできるようにアクセサを定義してやります。

```csharp
public string Title
{
    get { return (string)GetValue(TitleProperty); }
    set { SetValue(TitleProperty, value); }
}
```
[MSDN:DependencyObject.GetValue メソッド ](http://msdn.microsoft.com/ja-jp/library/system.windows.dependencyobject.getvalue\(v=vs.110\).aspx)
[MSDN:DependencyObject.SetValue メソッド ](http://msdn.microsoft.com/ja-jp/library/System.Windows.DependencyObject.SetValue\(v=vs.110\).aspx)

### 3.依存プロパティが変更されたとき呼ばれるコールバック関数

`DependencyProperty.Register`で依存プロパティを生成・登録するさい、FrameworkPropertyMetadataの属性として指定したプロパティ変更時の
コールバック関数です。依存プロパティの値が変更された場合に呼び出されます。

```csharp
private static void OnTitleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    // オブジェクトを取得して処理する
    DependencyPropertyTestControl ctrl = obj as DependencyPropertyTestControl;
    if (ctrl != null)
    {
        ctrl.TitleTextBlock.Text = ctrl.Title;
    }
}
```

```