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