【问题标题】:Sync ObservableCollection in ViewModel to ObservableCollection (of same type) in Model将 ViewModel 中的 ObservableCollection 同步到 Model 中的 ObservableCollection(同类型)
【发布时间】:2012-06-26 14:36:25
【问题描述】:

我目前有几个模型对象如下:

public class ModelBaseClass : INotifyPropertyChanged
{
    //Members omitted for brevity, but there is a DateTime property
    //that becomes important further down (see dummy method in application controller)      
}

还有一个:

public class ModelCollectionClass : INotifyPropertyChanged
{
    private ObservableCollection<ModelBaseClass> modelBaseClasses;
    public ObservableCollection<ModelBaseClass> ModelBaseClasses
    {
        get { return modelBaseClasses; }
        set
        {
            modelBaseClasses = value;
            OnPropertyChanged(new PropertyChangedEventArgs("ModelBaseClasses");
        }
    }

    private void modelBaseClasses_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        OnPropertyChanged(new PropertyChangedEventArgs("ModelBaseClasses"));
    }
}   

然后在我的一个视图视图模型中,我有这样的可观察集合:

private ObservableCollection<ModelBaseClass> modelBaseClasses;
public ObservableCollection<ModelBaseClass> ModelBaseClasses
{
    get{ return modelBaseClasses ?? (modelBaseClasses = new ObservableCollection<ModelBaseClass>()); }
    set
    {
        modelBaseClasses = value;                
        OnPropertyChanged(new PropertyChangedEventArgs("ModelBaseClasses"));
    }
}    

private ObservableCollection<ModelCollectionClass> modelCollectionClasses;
public ObservableCollection<ModelCollectionClass> ModelCollectionClasses
{
        get { return modelCollectionClasses ?? (modelCollectionClasses = new ObservableCollection<ModelCollectionClass>()); }
        set
        {
            modelCollectionClasses = value;
            OnPropertyChanged(new PropertyChangedEventArgs("ModelCollectionClasses"));                
        }
 }    

然后在我的应用程序控制器(将工作委托给视图模型)中,我有一个虚拟方法可以加载 ModelBaseClass 集合,如下所示:

for (int i = 0; i < 8; i++)
{
    myViewModel.ModelBaseClasses.Add(new ModelBaseClass()
    {
       DateTimeProperty = Convert.ToDateTime("06/2" + i + "/2012 09:00:00 AM")
       //Other properties get set as well, using the i variable...
    }
}

需要注意的是,这个方法中有不止一个 for 循环,这样我就可以处理大量数据了。

接下来,我有一个方法可以获取大量对象并按日期对它们进行分组,如下所示:

myViewModel.ModelBaseClasses
                .GroupBy(modelBaseClass => ((DateTime)modelBaseClass.DateTimeProperty).Date)
                .Select(group => group.ToList())
                .ToList()
                .ForEach(
                    list => myiewModel.ModelBaseCollections.Add(new ModelBaseCollection() { ModelBaseClasses = new ObservableCollection<ModelBaseClass>(list) })
                );

现在它开始变得更加复杂。在我的视图的 XAML 中,我声明了一个 ItemsControl,它的 ItemsSource 绑定到我的视图模型中的 ModelCollectionClasses 属性。它看起来像这样:

<ItemsControl ItemsSource="{Binding Path=DataContext.ModelCollectionClasses, RelativeSource={RelativeSource AncestorType={x:Type views:MyView}}}"
                              ItemTemplate="{StaticResource ItemsTemplate}">                    
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Width="{Binding ElementName=scroller, Path=ViewportWidth}"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

然后在这个特定视图的资源字典中,我有一个 DataTemplate 声明如下:

<DataTemplate x:Key="ItemsTemplate">
    <Grid DataContext="{Binding ModelBaseClasses}">            

        <DataGrid AutoGenerateColumns="False"
                  HeadersVisibility="None"
                  CanUserAddRows="False"
                  CanUserDeleteRows="False"
                  ItemsSource="{Binding Path=DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}"
                  SelectedItem="{Binding Path=DataContext.SelectedModelBaseClass, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type views:MyView}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">                

            <DataGrid.Columns>                                          
                    ...Omitted for brevity...
            </DataGrid.Columns>
        </DataGrid>            
    </Grid>
</DataTemplate>

现在,说了这么多,我得到了我最初想要的数据的所需可视化表示。但是,我现在遇到的问题是当我想删除 ModelBaseClass 对象之一时。因为 DataGrid 的 ItemsSource 被绑定到 ModelCollectionClass 的 ModelBaseClasses 属性,而不是我的视图模型中的 ModelBaseClasses,所以当我从视图模型中找到的 ModelCollectionClass 中删除 ModelBaseClass 时,我需要以某种方式通知 ModelCollectionClass此更改也是为了使 UI 能够正确更新。

我已经看到了一些其他示例,其中有些人创建了包装类来同步模型集合和视图模型集合,但是我很难用我自己的应用程序来实现这样的事情。任何见解或有用的提示/想法将不胜感激。

【问题讨论】:

  • 你确定有人会为你解析这么多代码吗?尽量简洁。
  • 我知道这是相当多的代码,但我试图尽可能透明。不过感谢您的关注。
  • 看看你如何删除 ModelBaseClass 会很有趣,但如果我猜对了,那么你也应该为你的 ModelBaseClass 和 ModelCollectionClass 提出一个 NotifyPropertyChanged。
  • BigL - 目前在我的一个 DataTemplateColumns 中,我指定了一个按钮,该按钮的 Command 属性绑定到 Delete Command。然后在该命令的 Executed 方法中,我执行以下操作: myViewModel.MyBaseClasses.Remove(myViewModel.SelectedBaseClass);但由于 DataGrid 未绑定到 myViewModel.MyBaseClasses,因此 UI 不会更新,因此我需要能够通知该 CollectionChanged 事件的所有 MyBaseCollection 集合。

标签: wpf mvvm observablecollection


【解决方案1】:

坦率地说,你的问题太复杂了,我不确定我是否得到你想要做的事情。但我注意到您的代码中有一件事:在ModelCollectionClass 中您设置了ModelBaseClass 属性,但通知您设置了ModelBaseClasses (es)。不确定它是否有帮助。

【讨论】:

  • 那是一个错字。让我试着总结一下:ModelCollectionClass 有 OC 称为 ModelBaseClasses。 MyViewModel 具有 OC(也称为 ModelBaseClasses),并在应用程序控制器中手动填充。 MyViewModel OC 称为 ModelCollectionClasses,并使用 viewmodel 中的 ModelBaseClasses 填充到应用程序控制器中。我可以从 VM 中的 ModelBaseClasses 中删除 ModelBaseClass 对象,但需要将此更改通知 ModelCollectionClass 中的 ModelBaseClasses,因为 UI 绑定到它,而不是 viewmodel 中的 ModelBaseClasses。
猜你喜欢
  • 2011-05-08
  • 2013-05-09
  • 1970-01-01
  • 2012-05-20
  • 2011-05-11
  • 1970-01-01
  • 2012-12-16
  • 2018-02-25
  • 2012-11-15
相关资源
最近更新 更多