I recently found how to add an event when changing a property of an Item in my ListView :
foreach (Profil item in gp.ListProfils)
{
if (item is INotifyPropertyChanged)
{
INotifyPropertyChanged observable = (INotifyPropertyChanged)item;
observable.PropertyChanged +=
new PropertyChangedEventHandler(ItemPropertyChanged);
}
}
Now, I would like to apply the modify to all selected items.
I found how to identify the name of property changed :
private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if(sender is Profil)
{
string myPropertyName = e.PropertyName;
Profil editedProfile = (Profil)sender;
foreach(Profil prf in this.SelectedProfiles)
{
//prf.NAME_PROPERTY = editedProfile.NAME_PROPERTY
if (!this.ListProfilToEdit.Contains(editedProfile))
{
this.ListProfilToEdit.Add(editedProfile);
}
}
}
}
But how can I replace the line in comment.
Concretely if I edited the field "Width", I want to change the width for all selected elements.
Is there a way to do it, without creating a separated function EditProperty(string nameProperty)
?
Here you need to be able to read a property dynamically from an object and then write it dynamically on another object.
You can use Expression Trees to generate Getters & Setters dynamically and them put in the cache.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace CoreAppMain
{
public class TypeAccessors<T> where T : class
{
//Getters
public static Dictionary<string, Func<T, object>> Getters = GetTypeGetters();
private static Dictionary<string, Func<T, object>> GetTypeGetters()
{
var _getters = new Dictionary<string, Func<T, object>>();
var props = typeof(T).GetProperties();
foreach (var p in props)
{
var entityParam = Expression.Parameter(typeof(T), "e");
Expression columnExpr = Expression.Property(entityParam, p);
Expression conversion = Expression.Convert(columnExpr, typeof(object));
var fct = Expression.Lambda<Func<T, object>>(conversion, entityParam).Compile();
_getters.Add(p.Name, fct);
}
return _getters;
}
//setters
public static Dictionary<string, Action<T, object>> Setters = GetTypeSetters();
public static Dictionary<string, Action<T, object>> GetTypeSetters()
{
var setters = new Dictionary<string, Action<T, object>>();
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
var propsToSet = typeof(T).GetProperties(flags)
.Where(x => x.CanWrite)
.ToList();
foreach (var field in propsToSet)
{
var propertyInfo = typeof(T).GetProperty(field.Name);
setters.Add(field.Name, GetPropertySetter<T>(propertyInfo));
}
return setters;
}
public static Action<TModel, object> GetPropertySetter<TModel>(PropertyInfo propertyInfo)
{
// Note that we are testing whether this is a value type
bool isValueType = propertyInfo.DeclaringType.IsValueType;
var method = propertyInfo.GetSetMethod(true);
var obj = Expression.Parameter(typeof(object), "o");
var value = Expression.Parameter(typeof(object));
// Note that we are using Expression.Unbox for value types
// and Expression.Convert for reference types
Expression<Action<TModel, object>> expr =
Expression.Lambda<Action<TModel, object>>(
Expression.Call(
isValueType ?
Expression.Unbox(obj, method.DeclaringType) :
Expression.Convert(obj, method.DeclaringType),
method,
Expression.Convert(value, method.GetParameters()[0].ParameterType)),
obj, value);
Action<TModel, object> action = expr.Compile();
return action;
}
}
}
Usage Example:
var cust1 = new Customer()
{
FirstName = "TOTOT",
LastName = "TITI"
};
var cust2 = new Customer()
{
FirstName = "XXXXXX",
LastName = "YYYYYY"
};
var value = TypeAccessors<Customer>.Getters[nameof(Customer.FirstName)](cust2);
TypeAccessors<Customer>.Setters[nameof(Customer.FirstName)](cust1, value);
Console.WriteLine(cust1.FirstName);
Console.ReadKey();