c# inotifypropertychanged c#-5.0 c#-6.0

¿Cómo implementar INotifyPropertyChanged en C#6.0?



c#-5.0 c#-6.0 (3)

La respuesta a esta pregunta se ha editado para decir que en C # 6.0, INotifyPropertyChanged se puede implementar con el siguiente procedimiento OnPropertyChanged:

protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }

Sin embargo, a partir de esa respuesta no queda claro cuál debe ser la definición de propiedad correspondiente. ¿Cómo se ve una implementación completa de INotifyPropertyChanged en C # 6.0 cuando se usa esta construcción?


Después de incorporar los diversos cambios, el código se verá así. He resaltado con comentarios las partes que cambiaron y cómo cada una ayuda.

public class Data : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { //C# 6 null-safe operator. No need to check for event listeners //If there are no listeners, this will be a noop PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } // C# 5 - CallMemberName means we don''t need to pass the property''s name protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer<T>.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } private string name; public string Name { get { return name; } //C# 5 no need to pass the property name anymore set { SetField(ref name, value); } } }


Sé que esta pregunta es antigua, pero aquí está mi implementación

Bindable utiliza un diccionario como una tienda de propiedades. Es bastante fácil agregar las sobrecargas necesarias para que una subclase administre su propio campo de respaldo utilizando parámetros de referencia.

  • Sin cuerda magica
  • Sin reflejo
  • Se puede mejorar para suprimir la búsqueda de diccionario predeterminada

El código:

public class Bindable : INotifyPropertyChanged { private Dictionary<string, object> _properties = new Dictionary<string, object>(); /// <summary> /// Gets the value of a property         /// <typeparam name="T"></typeparam> /// <param name="name"></param> /// <returns></returns> protected T Get<T>([CallerMemberName] string name = null) { object value = null; if (_properties.TryGetValue(name, out value)) return value == null ? default(T) : (T)value; return default(T); } /// <summary> /// Sets the value of a property /// </summary> /// <typeparam name="T"></typeparam> /// <param name="value"></param> /// <param name="name"></param> protected void Set<T>(T value, [CallerMemberName] string name = null) { if (Equals(value, Get<T>(name))) return; _properties[name] = value; OnPropertyChanged(name); } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }

utilizado de esta manera

public class Item : Bindable { public Guid Id { get { return Get<Guid>(); } set { Set<Guid>(value); } } }


Yo uso la misma lógica en mi proyecto. Tengo una clase base para todos los modelos de vista en mi aplicación:

using System.ComponentModel; using System.Runtime.CompilerServices; public class PropertyChangedBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }

Cada modelo de vista hereda de esta clase. Ahora, en el setter de cada propiedad solo necesito llamar a OnPropertyChanged() .

public class EveryViewModel : PropertyChangedBase { private bool initialized; public bool Initialized { get { return initialized; } set { if (initialized != value) { initialized = value; OnPropertyChanged(); } } }

¿Por qué funciona?

[CallerMemberName] es [CallerMemberName] automáticamente por el compilador con el nombre del miembro que llama a esta función. Cuando llamamos a OnPropertyChanged desde Initialized , el compilador coloca nameof(Initialized) como parámetro a OnPropertyChanged

Otro detalle importante a tener en cuenta.

El marco requiere que PropertyChanged y todas las propiedades a las que está vinculado sean public .