for WPF developers
MVVM パターンの要となるデータバインディング機能を実現するためには、 INotifyPropertyChanged インターフェースおよび ICommand インターフェースの実装が欠かせません。 しかし、いつも自前で実装するのは手間がかかるため、 YKToolkit.Controls.dll ではこれらのインターフェースの実装を済ませてあるクラスを YKToolkit.Bindings 名前空間で公開しています。
ページ内リンク
INotifyPropertyChanged インターフェースを実装している NotificationObject クラスは
次のように定義しています。
namespace YKToolkit.Bindings
{
using System.ComponentModel;
using System.Runtime.CompilerServices;
/// <summary>
/// INotifyPropertyChanged インターフェースを実装したプロパティ値変更通知機能を備えた抽象クラス
/// </summary>
public abstract class NotificationObject : INotifyPropertyChanged
{
#region INotifyPropertyChanged のメンバ
/// <summary>
/// プロパティ変更時に発生します。
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion // INotifyPropertyChanged のメンバ
/// <summary>
/// PropertyChanged イベントを発行します。
/// </summary>
/// <param name="propertyName">プロパティ名を指定します。省略した場合、所有するすべてのプロパティに対して変更通知をおこないます。</param>
protected virtual void RaisePropertyChanged([CallerMemberName]string propertyName = null)
{
var h = PropertyChanged;
if (h != null)
h(this, new PropertyChangedEventArgs(propertyName));
}
/// <summary>
/// プロパティ値に変更があった場合、プロパティ値を変更し、 PropertyChanged イベントを発行します。
/// </summary>
/// <typeparam name="T">プロパティの型</typeparam>
/// <param name="target">変更するプロパティを指定します。</param>
/// <param name="value">変更後のプロパティ値を指定します。</param>
/// <param name="propertyName">プロパティ名を指定します。省略した場合、所有するすべてのプロパティに対して変更通知をおこないます。</param>
/// <returns>プロパティ値に変更があった場合に true を返します。</returns>
protected virtual bool SetProperty<T>(ref T target, T value, string propertyName = null)
{
if (Equals(target, value))
return false;
target = value;
RaisePropertyChanged(propertyName);
return true;
}
}
}
using YKToolkit.Bindings;
public class MainViewModel : NotificationObject
{
}
private string name;
public string Name
{
get { return name; }
set { SetProperty(ref name, value); }
}
private int age;
public int Age
{
get { return age; }
set
{
if (SetProperty(ref age, value))
RaisePropertyChanged("CheatAge");
}
}
public int CheatAge
{
get { return Age > 40 ? Age - 10 : Age; }
}
ICommand インターフェースを実装している DelegateCommand クラスは 次のように定義しています。
namespace YKToolkit.Bindings
{
using System;
using System.Windows.Input;
public class DelegateCommand : ICommand
{
/// <summary>
/// コマンドの実体を保持します。
/// </summary>
private Action<object> _execute;
/// <summary>
/// コマンドの実行可能判別処理の実態を保持します。
/// </summary>
private Func<object, bool> _canExecute;
/// <summary>
/// 新しいインスタンスを生成します。
/// </summary>
/// <param name="execute">コマンドの実体を指定します。</param>
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// 新しいインスタンスを生成します。
/// </summary>
/// <param name="execute">コマンドの実体を指定します。</param>
/// <param name="canExecute">コマンドの実行可能判別処理の実体を指定します。</param>
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
/// <summary>
/// CanExecuteChanged イベントを発行します。
/// </summary>
public static void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
#region ICommand のメンバ
/// <summary>
/// コマンドの実行可能判別処理を実行します。
/// </summary>
/// <param name="parameter">コマンドパラメータを指定します。</param>
/// <returns>コマンドが実行可能であるとき true を返します。</returns>
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
/// <summary>
/// コマンドの実行可能判別条件が変更されたときに発生します。
/// </summary>
public event System.EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested += value; }
}
/// <summary>
/// コマンドを実行します。
/// </summary>
/// <param name="parameter">コマンドパラメータを指定します。</param>
public void Execute(object parameter)
{
if (_execute != null)
_execute(parameter);
}
#endregion ICommand のメンバ
}
}
private int counter;
private DelegateCommand buttonCommand;
public DelegateCommand ButtonCommand
{
get
{
return buttonCommand ?? (buttonCommand = new DelegateCommand(
_ =>
{
counter++;
},
_ =>
{
return counter < 10;
}));
}
}
YKToolkit.Controls.dll を導入したサンプルプログラムを公開しています。こちらを参考にして下さい。
Designed by CSS.Design Sample