Posted at

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

More than 5 years have passed since last update.

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


サンプルプログラム

テキストを表示するUserControlを作成する。

表示するテキストはTitleプロパティで指定する。

このTitleプロパティは依存プロパティとして実装する。


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";
}
}



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>


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>


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クラスのインスタンスにプロパティの初期値とプロパティの値が変更された場合に呼び出されるコールバック関数を指定して渡しています。

public static readonly DependencyProperty TitleProperty =

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

MSDN:DependencyProperty.Register メソッド


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

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

public string Title

{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}

MSDN:DependencyObject.GetValue メソッド

MSDN:DependencyObject.SetValue メソッド


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

DependencyProperty.Registerで依存プロパティを生成・登録するさい、FrameworkPropertyMetadataの属性として指定したプロパティ変更時の

コールバック関数です。依存プロパティの値が変更された場合に呼び出されます。

private static void OnTitleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)

{
// オブジェクトを取得して処理する
DependencyPropertyTestControl ctrl = obj as DependencyPropertyTestControl;
if (ctrl != null)
{
ctrl.TitleTextBlock.Text = ctrl.Title;
}
}