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_Automapper_Prism - Fatal编程技术网

C# 如何保持属性同步

C# 如何保持属性同步,c#,wpf,automapper,prism,C#,Wpf,Automapper,Prism,考虑到下面的类,我正在寻找使ExecuteQuery类的参数与Query类的参数保持同步的最佳方法 我在WPF项目中使用两个视图和viewmodels,一个视图用于定义模型查询,并将DataGrid绑定到参数。另一个视图是定义modelExecuteQuery,它有一个组合框来选择targetQuery对象。一旦选中它,我想将参数从查询复制到ExecuteQuery,这样它就可以同步,任何集合和属性的更改都可以相应地跟踪并反映在ExecuteQuery中 public class NamePar

考虑到下面的类,我正在寻找使
ExecuteQuery
类的参数与
Query
类的参数保持同步的最佳方法

我在WPF项目中使用两个视图和viewmodels,一个视图用于定义模型
查询
,并将DataGrid绑定到
参数
。另一个视图是定义model
ExecuteQuery
,它有一个组合框来选择target
Query
对象。一旦选中它,我想将参数从查询复制到ExecuteQuery,这样它就可以同步,任何集合和属性的更改都可以相应地跟踪并反映在ExecuteQuery中

public class NameParameter : Entity
{
    private string _name;
    public string Name
    {
        get => _name;
        set => SetProperty(ref _name, value);
    }
}

public class KeyValueParameter : ClientEntity
{
    private string _name;
    public string Name
    {
        get => _name;
        set => SetProperty(ref _name, value);
    }

    private string _value;
    public string Value
    {
        get => _value;
        set => SetProperty(ref _value, value);
    }
}

public class Query
{
    private ObservableCollection<NameParameter> _parameters = new ObservableCollection<NameParameter>();
    public IEnumerable<NameParameter> Parameters => _parameters.AsEnumerable();

    public void AddParameter()
    {
        _parameters.Add(new NameParameter());
    }
}

public class ExecuteQuery
{
    private Query _query;
    public Query Query
    {
        get => _query;
        set => SetProperty(ref _query, value);
    }

    private ObservableCollection<KeyValueParameter> _parameters = new ObservableCollection<KeyValueParameter>();
    public IEnumerable<KeyValueParameter> Parameters => _parameters.AsEnumerable();
}

公共类名称参数:实体
{
私有字符串\u名称;
公共字符串名
{
get=>\u name;
set=>SetProperty(参考名称、值);
}
}
公共类KeyValueParameter:客户实体
{
私有字符串\u名称;
公共字符串名
{
get=>\u name;
set=>SetProperty(参考名称、值);
}
私有字符串_值;
公共字符串值
{
获取=>\u值;
set=>SetProperty(参考值,值);
}
}
公共类查询
{
私有ObservableCollection_参数=新ObservableCollection();
public IEnumerable Parameters=>_Parameters.AsEnumerable();
public void AddParameter()
{
_添加(新名称参数());
}
}
公共类执行器
{
私有查询(private Query);;
公共查询
{
get=>\u查询;
set=>SetProperty(ref\u查询,值);
}
私有ObservableCollection_参数=新ObservableCollection();
public IEnumerable Parameters=>_Parameters.AsEnumerable();
}
到目前为止,我已经使用Automapper映射了以下配置的不同类型,但我仍然不确定它是否是解决此问题的正确方法

var configuration = new MapperConfiguration(cfg => {
    cfg.AllowNullCollections = true;
    cfg.CreateMap<NameParameter, KeyValueParameter>()
        .ForMember(d => d.Value, o => o.Ignore());
});
var配置=新的MapperConfiguration(cfg=>{
cfg.AllowNullCollections=true;
cfg.CreateMap()
.ForMember(d=>d.Value,o=>o.Ignore());
});

我可以通过一些努力来实现这一点,但在这里问这个问题是为了了解一个专家解决方案,以最小的代码更改来解决此类重复问题,并确定大多数人使用的任何模式。

感谢Holger的评论。最后,这就是我如何通过这么多看起来有点脏的事件连接实现它的。不确定是否有更好更干净的方法

我发布这个问题的初衷是寻找任何从我的域对象中抽象出这个逻辑的熟练方法

public class Query
{
    private ObservableCollection<NameParameter> _parameters = new ObservableCollection<NameParameter>();
    public IEnumerable<NameParameter> Parameters => _parameters.AsEnumerable();

    public void AddParameter()
    {
        _parameters.Add(new NameParameter());
    }

    public void SubscribeParametersCollectionChanges(NotifyCollectionChangedEventHandler handler)
    {
        _parameters.CollectionChanged += handler;
    }
}

public class ExecuteQuery
{
    public ExecuteQuery()
    {
        PropertyChanged += ExecuteQuery_PropertyChanged;
    }

    private void ExecuteQuery_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(Query))
            OnQuerySelection();
    }

    private Query _query;
    public Query Query
    {
        get => _query;
        set => SetProperty(ref _query, value);
    }

    private ObservableCollection<KeyValueParameter> _parameters = new ObservableCollection<KeyValueParameter>();
    public IEnumerable<KeyValueParameter> Parameters => _parameters.AsEnumerable();

    private void OnQuerySelection()
    {
        // subscribe to NamedParameters collection changed events
        DataElement?.SubscribeParametersCollectionChanges(Parameters_CollectionChanged);
        // calling this method explicitly so that if there are already Parameters in Source, bring them right away
        Parameters_CollectionChanged(this, null);
    }

    private void Parameters_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // subscribe to each object property changed events in NamedParameters 
        foreach (var namedParameter in Query.Parameters)
            if (namedParameter is INotifyPropertyChanged npc)
                npc.PropertyChanged += Parameters_PropertyChanged;
        // copying parameters from source to target
        _parameters = new ObservableCollection<KeyValueParameter>(
            Query.Parameters.Select(x => new KeyValueParameter(x.Name)));
        // raising event to notify UI for this change
        RaisePropertyChanged(nameof(Parameters));
    }

    private void Parameters_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(Name))
        {
            var namedParameter = Query.Parameters.ToList();
            for (var i = 0; i < namedParameter.Count; i++)
                _parameters[i].Name = namedParameter[i].Name;
        }
    }
}
公共类查询
{
私有ObservableCollection_参数=新ObservableCollection();
public IEnumerable Parameters=>_Parameters.AsEnumerable();
public void AddParameter()
{
_添加(新名称参数());
}
public void SubscribeParameters集合更改(NotifyCollectionChangedEventHandler处理程序)
{
_parameters.CollectionChanged+=处理程序;
}
}
公共类执行器
{
公共行政机构
{
PropertyChanged+=ExecuteQuery\u PropertyChanged;
}
私有void ExecuteQuery\u PropertyChanged(对象发送方,PropertyChangedEventArgs e)
{
if(e.PropertyName==nameof(查询))
OnQuerySelection();
}
私有查询(private Query);;
公共查询
{
get=>\u查询;
set=>SetProperty(ref\u查询,值);
}
私有ObservableCollection_参数=新ObservableCollection();
public IEnumerable Parameters=>_Parameters.AsEnumerable();
私有void OnQuerySelection()
{
//订阅NamedParameters集合更改事件
DataElement?.SubscribeParametersCollectionChanges(参数\u CollectionChanged);
//显式调用此方法,以便在源代码中已经存在参数时,立即将它们带到源代码中
参数_CollectionChanged(此参数为空);
}
私有void参数\u CollectionChanged(对象发送方,NotifyCollectionChangedEventArgs e)
{
//订阅NamedParameters中的每个对象属性更改事件
foreach(Query.Parameters中的变量namedParameter)
if(命名参数为INotifyPropertyChanged npc)
npc.PropertyChanged+=参数\u PropertyChanged;
//将参数从源复制到目标
_参数=新的ObservableCollection(
选择(x=>newkeyvalueparameter(x.Name));
//正在引发事件以通知此更改的UI
RaisePropertyChanged(参数名称));
}
私有void参数\u PropertyChanged(对象发送方,PropertyChangedEventArgs e)
{
如果(e.PropertyName==nameof(Name))
{
var namedParameter=Query.Parameters.ToList();
对于(变量i=0;i
是否有任何原因导致数据存储两次?为什么ExecuteQuery.Parameters不能只返回转换格式的_query.Parameters?查询列出了可由多个ExecuteQuery使用的命名参数,它应该以KeyValueParameter的形式具有相同的参数来存储附加值。您可以将其转换,然后访问ExecuteQuery.Parameters。我看不出有什么理由去储存它。ExecuteQuery并没有修改它的副本,或者是吗?我将限制对来自查询的名称的修改,但最终它应该单独维护这些数据以保存每个参数的值。目前,我在ExecuteQuery中有一个DataGrid,显示只读名称列和可编辑值列。不,CollectionChanged涵盖了所有内容。添加/删除/编辑项目。处理程序看起来像
\u parameters=\u query.parameters.Select(x=>newkeyvalueparameter(x.whatever..)
这一行程序不够优雅?