Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 确定更改了哪些属性,并编辑所有选定项_C#_Wpf_Listview_Inotifypropertychanged - Fatal编程技术网

C# 确定更改了哪些属性,并编辑所有选定项

C# 确定更改了哪些属性,并编辑所有选定项,c#,wpf,listview,inotifypropertychanged,C#,Wpf,Listview,Inotifypropertychanged,我最近发现了如何在更改ListView中项目的属性时添加事件: foreach (Profil item in gp.ListProfils) { if (item is INotifyPropertyChanged) { INotifyPropertyChanged observable = (INotifyPropertyChanged)item; observable.PropertyChanged += new Pr

我最近发现了如何在更改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(stringnameproperty)

有没有一种方法可以做到这一点,而不用创建一个单独的函数EditProperty(string nameProperty)

创建单独的方法与否取决于良好的设计和干净的代码,它不会以任何方式影响问题的核心。您始终可以创建单独的方法或在现有方法中编写代码

但是我如何替换注释中的行呢

现在还不清楚你在做什么,所以我怀疑你所问的问题是否可以用不同的方式解决,但事实上,你只是要求通过知道实例的名称来读写它们的属性。您将需要为此使用

为了执行后期绑定,访问在运行时创建的类型上的方法。参见主题

假设您的房产是公共的,这应该可以:

var propertyInfo = typeof(Profil).GetProperty(myPropertyName);
var value = propertyInfo.GetValue(editedProfile, null);

foreach(Profil prf in this.SelectedProfiles)
{
   propertyInfo.SetValue(prf, value);
   
   // ...other code.
}
也就是说,仔细使用反射,以便进一步阅读:


在这里,您需要能够从一个对象动态读取属性,然后在另一个对象上动态写入属性

可以使用表达式树动态生成getter和setter,并将它们放入缓存中

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;
        }

    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Linq.Expressions;
运用系统反思;
名称空间CoreAppMain
{
公共类类型访问器,其中T:class
{
//吸气剂
公共静态字典Getters=GetTypeGetters();
私有静态字典GetTypeGetters()
{
var_getters=新字典();
var props=typeof(T).GetProperties();
foreach(道具中的var p)
{
var entityParam=表达式参数(typeof(T),“e”);
Expression columnExpr=Expression.Property(entityParam,p);
表达式转换=Expression.Convert(columnExpr,typeof(object));
var fct=Expression.Lambda(转换,entityParam.Compile();
_getters.Add(p.Name,fct);
}
返回获取者;
}
//二传手
公共静态字典Setters=GetTypeSetters();
公共静态字典GetTypeSetters()
{
var setters=newdictionary();
const BindingFlags flags=BindingFlags.Public | BindingFlags.Instance;
var propsToSet=typeof(T).GetProperties(标志)
.Where(x=>x.CanWrite)
.ToList();
foreach(propsToSet中的var字段)
{
var propertyInfo=typeof(T).GetProperty(field.Name);
Add(field.Name,GetPropertySetter(propertyInfo));
}
返回设置器;
}
公共静态操作GetPropertySetter(PropertyInfo PropertyInfo)
{
//请注意,我们正在测试这是否是值类型
bool isValueType=propertyInfo.DeclaringType.isValueType;
var method=propertyInfo.GetSetMethod(true);
var obj=表达式参数(typeof(object),“o”);
var值=表达式参数(typeof(object));
//请注意,我们对值类型使用Expression.Unbox
//和表达式。转换为引用类型
表达式表达式=
Lambda(
表情,打电话(
是ValueType吗?
表达式.Unbox(对象,方法.DeclaringType):
表达式.Convert(obj,方法.DeclaringType),
方法,,
Expression.Convert(值,方法.GetParameters()[0].ParameterType)),
obj,值);
Action Action=expr.Compile();
返回动作;
}
}
}
用法示例:

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();
var cust1=新客户()
{
FirstName=“TOTOT”,
LastName=“TITI”
};
var cust2=新客户()
{
FirstName=“XXXXXX”,
LastName=“yyyyy”
};
var value=TypeAccessors.Getters[nameof(Customer.FirstName)](cust2);
打字机访问器.设置器[名称(客户.名字)](客户1,值);
Console.WriteLine(cust1.FirstName);
Console.ReadKey();

谢谢,事实上这正是我最后决定要做的事情(你写的那段代码)。因为我还注意到,我只需要对某些字段启用“多重编辑”,而不是对所有字段启用“多重编辑”,所以我做了一个函数,仅当字段名对应于这两个字段时才执行此操作。