Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.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# wpf mvvm处理ViewModel中的集合属性及其值在模型中的传播_C#_Wpf_Design Patterns_Mvvm_Binding - Fatal编程技术网

C# wpf mvvm处理ViewModel中的集合属性及其值在模型中的传播

C# wpf mvvm处理ViewModel中的集合属性及其值在模型中的传播,c#,wpf,design-patterns,mvvm,binding,C#,Wpf,Design Patterns,Mvvm,Binding,ViewModel中绑定到View中元素的属性通常从 某些模型类实例,当值在视图中更新时,该属性将值的更改传播到基础模型类实例中。 但是,如果在ViewModel中有一个属性返回,例如根据值构造的observedcollection 在模型中,视图中的值的更改仅更改ObservableCollection中的值。它不会将值的更改传播到基础模型类实例中 例如,您有一个模式对话框(视图),显示该对话框及其数据上下文(视图模型),并且视图模型包含模型类的实例。 现在 情况A)关闭对话框时,您的Vie

ViewModel
中绑定到
View
中元素的属性通常从 某些模型类实例,当值在
视图中更新时,该属性将值的更改传播到基础模型类实例中。

但是,如果在
ViewModel
中有一个属性返回,例如根据值构造的
observedcollection
在模型中,
视图中的值的更改
仅更改ObservableCollection中的值。它不会将值的更改传播到基础模型类实例中

例如,您有一个模式对话框(
视图
),显示该对话框及其数据上下文(
视图模型
),并且视图模型包含模型类的实例。 现在

  • 情况A)关闭对话框时,您的ViewModel只有返回非集合类型(int、string…)的属性 您知道模型类实例具有更新的值

  • 情况B)您有一个ViewModel,该ViewModel的属性公开了一个ObservableCollection,当您关闭对话框时,model类 实例不包含更新的值

处理这一问题的常见模式/做法是什么?
我认为您可以有一个方法将
ViewModel
中存在的数据写入模型实例,并在对话框关闭时调用此方法。但就MVVM和WPF的哲学而言,这似乎是不自然的

请记住,前面提到的例子只是一个例子。这通常适用于任何视图模型交互


如果有人不明白我想描述的内容:

让我们来上一节示范课

public enum A
{
    A1,
    A2,
    A3    
}

public class MyModel
{
    private float[][] array;

    public MyModel()
    {
        array = new float[Enum.GetNames(typeof(A)).Length][];
        foreach (A a in EnumUtil.GetValues<A>())
        {
            array[(int) a] = new float[3]; // any number, really, but it will be referenced later in text
        }
    }

    public A EnumerationA { get; set; }
    public float this[A a, int b]
    {
        get
        {
            return array[(int) a][b];
        }
        set
        {
            array[(int)a][b] = value;
        }
    }        
    public float[] ArraySlice
    {
        get
        {
            return array[(int) EnumerationA];
        }
    }
}
公共枚举A
{
A1,
A2,
A3
}
公共类MyModel
{
专用浮点[][]数组;
公共MyModel()
{
array=newfloat[Enum.GetNames(typeof(A)).Length][];
foreach(EnumUtil.GetValues()中的A)
{
数组[(int)a]=new float[3];//实际上可以是任何数字,但稍后将在文本中引用它
}
}
公共枚举{get;set;}
公共浮动本[A,int b]
{
得到
{
返回数组[(int)a][b];
}
设置
{
数组[(int)a][b]=值;
}
}        
公共浮动[]阵列片
{
得到
{
返回数组[(int)枚举A];
}
}
}
和一个ViewModel类

public class MyViewModel : ViewModelBase
{
    private MyModel _myModel;
    private ObservableCollection<float>[] _tmp = new ObservableCollection<float>[Enum.GetNames(typeof(A)).Length];

    public MyViewModel()
    {
        // in constructor we will add 3 values to each collection
    }

    public A EnumerationA
    {
        get
        {
            return _myModel.EnumerationA;
        }
        set
        {
            if (Enum.Equals(_myModel.EnumerationA, value) == false)
            {
                _myModel.EnumerationA = value;
                RaisePropertyChanged("EnumerationA");
                RaisePropertyChanged("ArraySlice");
            }
        }
    }

    public ObservableCollection<float> ArraySlice
    {
        get
        {
            return _tmp[(int) EnumerationA];
        }
    }       
}
公共类MyViewModel:ViewModelBase { 私有MyModel\u MyModel; 私有ObservableCollection[]_tmp=新ObservableCollection[Enum.GetNames(typeof(A)).Length]; 公共MyViewModel() { //在构造函数中,我们将向每个集合添加3个值 } 公共普查 { 得到 { 返回_myModel.EnumerationA; } 设置 { if(Enum.Equals(_myModel.EnumerationA,value)==false) { _myModel.EnumerationA=值; RaisePropertyChanged(“枚举A”); RaisePropertyChanged(“ArraySlice”); } } } 公共可观测采集阵列切片 { 得到 { 返回_tmp[(int)枚举a]; } } }
ArraySlice可以绑定到任何数据网格等…
因此,在本例中,当用户完成时,存储在ObservableCollections数组中的值不会保存在模型实例中
但是,如果我们没有返回ObservaleCollection的属性,而是有三个属性,每个属性都返回float,那么这些值将很容易传播到属性setter中的底层模型类实例中


最好我欢迎一个想法/解决方案,在视图/视图模型/模型之间的交互结束后,不需要我做任何事情

@Sheridan-你好,你告诉我我可以通知你这个问题-在你的情况下我没有得到什么A,为什么你说简单属性直接传播到模型?是否将值保存回ViewModel中每个setter中的模型?@Alejandro是的,对于简单值,我在ViewModel中没有备份ViewModel属性的字段。我通常只使用模型的字段/属性。因此,在setter中,我直接写回模型。我认为这是正确的方法。这有什么问题吗?我真的不喜欢这种方法,但这当然是可能的。问题是,它绕过了任何验证用户输入的机会,这可能会使模型在某些点处于无效状态,甚至可能对足够复杂的属性和组合抛出异常。此外,如果用户想要取消编辑,您也无法轻松地取消用户编辑。我的首选方法是将所有内容映射到ViewModel,然后将其映射回,或者使用DTO并绑定到该DTO,然后将其转换回模型。另一个选项是订阅
CollectionChanged
,然后从模型中添加/删除