プロパティがあり、名前はImageFullPath1です
public string ImageFullPath1 {get; set; }
値が変更されるたびにイベントを発生させます。 INotifyPropertyChanged
の変更は承知していますが、イベントを使用して変更したいです。
INotifyPropertyChanged
インターフェースは、イベントで実装されます。このインターフェイスには、PropertyChanged
という1つのメンバーしかありません。これは、コンシューマがサブスクライブできるイベントです。
リチャードが投稿したバージョンは安全ではありません。このインターフェイスを安全に実装する方法は次のとおりです。
_public class MyClass : INotifyPropertyChanged
{
private string imageFullPath;
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, e);
}
protected void OnPropertyChanged(string propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
public string ImageFullPath
{
get { return imageFullPath; }
set
{
if (value != imageFullPath)
{
imageFullPath = value;
OnPropertyChanged("ImageFullPath");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
_
これは次のことを行うことに注意してください。
プロパティ変更通知メソッドを抽象化して、これを他のプロパティに簡単に適用できるようにします。
PropertyChanged
デリゲートbeforeのコピーを作成して、呼び出しを試みます(これを行わないと、競合状態が発生します)。
INotifyPropertyChanged
インターフェイスを正しく実装します。
変更されたspecificプロパティの通知を追加作成する場合は、次のコードを追加できます。
_protected void OnImageFullPathChanged(EventArgs e)
{
EventHandler handler = ImageFullPathChanged;
if (handler != null)
handler(this, e);
}
public event EventHandler ImageFullPathChanged;
_
次に、OnImageFullPathChanged(EventArgs.Empty)
行の後にOnPropertyChanged("ImageFullPath")
行を追加します。
.Net 4.5があるため、 CallerMemberAttribute
が存在します。これにより、ソースコード内のプロパティ名のハードコードされた文字列を取り除くことができます。
_ protected void OnPropertyChanged(
[System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
public string ImageFullPath
{
get { return imageFullPath; }
set
{
if (value != imageFullPath)
{
imageFullPath = value;
OnPropertyChanged();
}
}
}
_
私はAaronaughtとほぼ同じパターンを使用しますが、多くのプロパティがある場合は、少し汎用的なメソッドマジックを使用してコードをもう少し増やすのが良いかもしれません [〜#〜] dry [〜#〜]
public class TheClass : INotifyPropertyChanged {
private int _property1;
private string _property2;
private double _property3;
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) {
PropertyChangedEventHandler handler = PropertyChanged;
if(handler != null) {
handler(this, e);
}
}
protected void SetPropertyField<T>(string propertyName, ref T field, T newValue) {
if(!EqualityComparer<T>.Default.Equals(field, newValue)) {
field = newValue;
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
}
public int Property1 {
get { return _property1; }
set { SetPropertyField("Property1", ref _property1, value); }
}
public string Property2 {
get { return _property2; }
set { SetPropertyField("Property2", ref _property2, value); }
}
public double Property3 {
get { return _property3; }
set { SetPropertyField("Property3", ref _property3, value); }
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
通常、OnPropertyChangedメソッドを仮想化して、サブクラスがそれをオーバーライドしてプロパティの変更をキャッチできるようにします。
プロパティが変更されたときにイベントを発生させることは、まさにINotifyPropertyChangedが行うことです。 INotifyPropertyChangedを実装するために必要なメンバーが1つあり、それがPropertyChangedイベントです。自分で実装したものはすべて、おそらくその実装と同じになるため、使用しないことの利点はありません。
public event EventHandler ImageFullPath1Changed;
public string ImageFullPath1
{
get
{
// insert getter logic
}
set
{
// insert setter logic
// EDIT -- this example is not thread safe -- do not use in production code
if (ImageFullPath1Changed != null && value != _backingField)
ImageFullPath1Changed(this, new EventArgs(/*whatever*/);
}
}
とは言うものの、私はライアンに完全に同意します。このシナリオは、まさにINotifyPropertyChangedが存在する理由です。
(自動プロパティの代わりに)バッキングフィールドを使用するようにプロパティを変更する場合、次のことができます。
public event EventHandler ImageFullPath1Changed;
private string _imageFullPath1 = string.Empty;
public string ImageFullPath1
{
get
{
return imageFullPath1 ;
}
set
{
if (_imageFullPath1 != value)
{
_imageFullPath1 = value;
EventHandler handler = ImageFullPathChanged;
if (handler != null)
handler(this, e);
}
}
}