确定 属性 更改的内容,并编辑所有选定的项目
identify what property changed, and edit all selected Items
我最近发现如何在我的 ListView 中更改 属性 项时添加事件:
foreach (Profil item in gp.ListProfils)
{
if (item is INotifyPropertyChanged)
{
INotifyPropertyChanged observable = (INotifyPropertyChanged)item;
observable.PropertyChanged +=
new PropertyChangedEventHandler(ItemPropertyChanged);
}
}
现在,我想将修改应用于所有选定的项目。
我发现如何识别 属性 的名称已更改:
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);
}
}
}
}
但是我如何替换评论中的行。
具体来说,如果我编辑了“宽度”字段,我想更改所有选定元素的宽度。
有没有办法做到这一点,而无需创建单独的函数 EditProperty(string nameProperty)
?
Is there a way to do it, without creating a separated function EditProperty(string nameProperty)?
是否创建一个单独的方法是一个好的设计和干净的代码的问题,它不会以任何方式影响问题的核心。您始终可以创建单独的方法或在现有方法中编写代码。
But how can I replace the line in comment.
不太清楚你在做什么,所以我怀疑你问的问题是否可以用不同的方式解决,但事实上,你要求只知道读写实例的属性他们的名字。您将需要为此使用 Reflection。
For performing late binding, accessing methods on types created at run time. See the topic Dynamically Loading and Using Types.
假设您的属性是 public,这应该有效:
var propertyInfo = typeof(Profil).GetProperty(myPropertyName);
var value = propertyInfo.GetValue(editedProfile, null);
foreach(Profil prf in this.SelectedProfiles)
{
propertyInfo.SetValue(prf, value);
// ...other code.
}
也就是说,小心使用反射,进一步阅读:
- Reflection: Is using reflection still “bad” or “slow”?
- If reflection is inefficient, when is it most appropriate?
这里需要能够从一个对象中动态读取一个属性,然后在另一个对象上动态写入。
您可以使用表达式树动态生成 Getters 和 Setters 并将它们放入缓存中。
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;
}
}
}
用法示例:
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();
我最近发现如何在我的 ListView 中更改 属性 项时添加事件:
foreach (Profil item in gp.ListProfils)
{
if (item is INotifyPropertyChanged)
{
INotifyPropertyChanged observable = (INotifyPropertyChanged)item;
observable.PropertyChanged +=
new PropertyChangedEventHandler(ItemPropertyChanged);
}
}
现在,我想将修改应用于所有选定的项目。
我发现如何识别 属性 的名称已更改:
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);
}
}
}
}
但是我如何替换评论中的行。
具体来说,如果我编辑了“宽度”字段,我想更改所有选定元素的宽度。
有没有办法做到这一点,而无需创建单独的函数 EditProperty(string nameProperty)
?
Is there a way to do it, without creating a separated function EditProperty(string nameProperty)?
是否创建一个单独的方法是一个好的设计和干净的代码的问题,它不会以任何方式影响问题的核心。您始终可以创建单独的方法或在现有方法中编写代码。
But how can I replace the line in comment.
不太清楚你在做什么,所以我怀疑你问的问题是否可以用不同的方式解决,但事实上,你要求只知道读写实例的属性他们的名字。您将需要为此使用 Reflection。
For performing late binding, accessing methods on types created at run time. See the topic Dynamically Loading and Using Types.
假设您的属性是 public,这应该有效:
var propertyInfo = typeof(Profil).GetProperty(myPropertyName);
var value = propertyInfo.GetValue(editedProfile, null);
foreach(Profil prf in this.SelectedProfiles)
{
propertyInfo.SetValue(prf, value);
// ...other code.
}
也就是说,小心使用反射,进一步阅读:
- Reflection: Is using reflection still “bad” or “slow”?
- If reflection is inefficient, when is it most appropriate?
这里需要能够从一个对象中动态读取一个属性,然后在另一个对象上动态写入。
您可以使用表达式树动态生成 Getters 和 Setters 并将它们放入缓存中。
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;
}
}
}
用法示例:
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();