Estoy jugando con la idea de pasar una asignación de propiedad a un método como árbol de expresiones. El método invocaría la expresión para que la propiedad se asignara correctamente, y luego olfatear el nombre de la propiedad que acaba de asignarse para poder levantar el evento PropertyChanged. La idea es que me gustaría poder usar propiedades automáticas delgadas en mis WPF ViewModels y aún tener activado el evento PropertyChanged.Asignar propiedad con un ExpressionTree
yo soy un ignorante con ExpressionTrees, así que estoy esperando que alguien me puede apuntar en la dirección correcta:
public class ViewModelBase {
public event Action<string> PropertyChanged = delegate { };
public int Value { get; set; }
public void RunAndRaise(MemberAssignment Exp) {
Expression.Invoke(Exp.Expression);
PropertyChanged(Exp.Member.Name);
}
}
El problema es que no estoy seguro de cómo llamar a esto. Este ingenuo intento fue rechazado por el compilador por razones que estoy seguro será obvio para cualquier persona que pueda responder a esta:
ViewModelBase vm = new ViewModelBase();
vm.RunAndRaise(() => vm.Value = 1);
EDITAR
Gracias @svick para la respuesta perfecta. Moví una pequeña cosa y la convertí en un método de extensión. Aquí está el ejemplo de código completo con unidad de prueba:
[TestClass]
public class UnitTest1 {
[TestMethod]
public void TestMethod1() {
MyViewModel vm = new MyViewModel();
bool ValuePropertyRaised = false;
vm.PropertyChanged += (s, e) => ValuePropertyRaised = e.PropertyName == "Value";
vm.SetValue(v => v.Value, 1);
Assert.AreEqual(1, vm.Value);
Assert.IsTrue(ValuePropertyRaised);
}
}
public class ViewModelBase : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public void OnPropertyChanged(string propertyName) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public class MyViewModel : ViewModelBase {
public int Value { get; set; }
}
public static class ViewModelBaseExtension {
public static void SetValue<TViewModel, TProperty>(this TViewModel vm, Expression<Func<TViewModel, TProperty>> exp, TProperty value) where TViewModel : ViewModelBase {
var propertyInfo = (PropertyInfo)((MemberExpression)exp.Body).Member;
propertyInfo.SetValue(vm, value, null);
vm.OnPropertyChanged(propertyInfo.Name);
}
}
+1 para una respuesta más completa. – Ani
ya + 1ed, y ahora acepto, gracias por la gran respuesta –
por cierto, con respecto a su segunda respuesta, evitando el código voluminoso como que es lo que estaba tratando de evitar en primer lugar. Tomé su respuesta y la convertí en un método de extensión, que debería permitirme establecer propiedades aotu y hacer que el evento propertyChanged se active automáticamente. Gracias de nuevo. –