Basisklasse, welche neben Benachrichtigungen durch INotifyPropertyChanged zusätzlich ein IsChanged Event für jede Property zur Verfügung stellt.
Dabei werden keine string Parameter verwendet, was Probleme bei einem Refactoring vermeidet.Beispiel Implementierung INotifyPropertyChanged:
class Person : NotificationObjectWithPropertyIsChangedEvents
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
if (_Name == value) return;
_Name = value;
RaisePropertyChanged(() => Name);
}
}
public Person(string name) {
Name = name;
}
}
Beispiel Verwendung IsChanged Event:
var p = new Person("Max");
p.Property(() => p.Name).IsChanged += (s,e) => { Console.WriteLine("Neuer Name: " + (s as Person).Name); };
p.Name = "Meier";
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
namespace eac.Utilities
{
/// <summary>
/// Eine Hilfsklasse, welche Events für Propery-IsChanged generisch bereit stellt
/// obj.Property(() => obj.PROPERTY).IsChanged += (s,e) => { ... };
/// </summary>
public class NotificationObjectWithPropertyIsChangedEvents : Object, INotifyPropertyChanged
{
public sealed class NotificationObjectWithPropertyIsChangedEventHolder
{
public event EventHandler IsChanged;
readonly NotificationObjectWithPropertyIsChangedEvents _obj;
public NotificationObjectWithPropertyIsChangedEventHolder(NotificationObjectWithPropertyIsChangedEvents obj)
{
_obj = obj;
}
public void RaiseIsChanged()
{
var tmp = IsChanged; // in lokale variable kompieren um thread save zu sein
if (tmp != null) tmp(_obj, EventArgs.Empty);
}
}
public NotificationObjectWithPropertyIsChangedEvents()
{
this.PropertyChanged += NotificationObjectWithEvent_PropertyChanged;
}
readonly Dictionary<string, NotificationObjectWithPropertyIsChangedEventHolder> _eventHandler = new Dictionary<string, NotificationObjectWithPropertyIsChangedEventHolder>();
public NotificationObjectWithPropertyIsChangedEventHolder Property<T>(Expression<Func<T>> propertyExpression)
{
var propName = ExtractPropertyName(propertyExpression);
if (_eventHandler.ContainsKey(propName)) return _eventHandler[propName];
var nh = new NotificationObjectWithPropertyIsChangedEventHolder(this);
_eventHandler.Add(propName, nh);
return nh;
}
void NotificationObjectWithEvent_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
foreach (var item in _eventHandler.Where(s => s.Key == e.PropertyName))
item.Value.RaiseIsChanged();
}
// **************
// ab hier von Prism 4.0 übernommen (http://compositewpf.codeplex.com/)
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected virtual void RaisePropertyChanged(string propertyName)
{
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if (propertyChanged != null)
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
/// <summary>
/// Raises this object's PropertyChanged event for each of the properties.
/// </summary>
/// <param name="propertyNames">The properties that have a new value.</param>
protected void RaisePropertyChanged(params string[] propertyNames)
{
if (propertyNames == null)
throw new System.ArgumentNullException("propertyNames");
string[] strArrays = propertyNames;
foreach (var str in strArrays)
this.RaisePropertyChanged(str);
}
protected void RaisePropertyChanged<T>(System.Linq.Expressions.Expression<System.Func<T>> propertyExpression)
{
string str = ExtractPropertyName<T>(propertyExpression);
this.RaisePropertyChanged(str);
}
/// <summary>
/// Raised when a property on this object has a new value.
/// </summary>
public virtual event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
static string ExtractPropertyName<T>(System.Linq.Expressions.Expression<System.Func<T>> propertyExpression)
{
if (propertyExpression == null)
{
throw new System.ArgumentNullException("propertyExpression");
}
System.Linq.Expressions.MemberExpression body = propertyExpression.Body as System.Linq.Expressions.MemberExpression;
if (body == null)
{
throw new System.ArgumentException("The expression is not a member access expression");
}
System.Reflection.PropertyInfo member = body.Member as System.Reflection.PropertyInfo;
if (member == null)
{
throw new System.ArgumentException("The member access expression does not access a property");
}
System.Reflection.MethodInfo getMethod = member.GetGetMethod(true);
if (getMethod.IsStatic)
{
throw new System.ArgumentException("The referenced property is a static property");
}
return body.Member.Name;
}
}
}
Kommentare zum Snippet