WPF / MVVM - 绑定子控件的集合

时间:2016-07-13 12:00:11

标签: wpf mvvm data-binding

WPF / MVVM大师的一些建议,请等。

我来自Windows窗体后台,我正在将个人项目从VB.NET移植到WPF。我开始直接重写代码隐藏文件中的逻辑,尽管有一个离散的数据访问层。然而,我发现了MVVM并且我做错了这一切'并且应该将逻辑抽象为访问数据模型的视图模型。我想我已经吸收了新的范例,我的代码背后的代码现在(几乎)是空的。

(顺便说一句,我接受MVVM背后的理由,但由于所有的管道和#,我不确定“更容易测试和调试”的论点。 39;关于路由事件和命令等,我很欣赏这种需要,但在我看来有时候会模糊而不是澄清发生了什么。但我是一个非常新手,也许它会伴随着练习。)

无论如何 - 这就是让我挠头的原因;该应用程序是潜水中心的潜水计划/录音工具。从逻辑上讲,它就像日历或日记应用程序一样,需要记录每次潜水的时间和地点以及每次潜水的人员。主屏幕类似于日记的一页,我有一个用户控件封装潜水信息。在更改选定日期时,日记页面将被清除并重新填充新选定日期的潜水。视图模型检索并公开“潜水”列表。新日期的对象(类)。容器是一个Stackpanel,我想清除它的子项,然后创建新的Dive用户控件并将其添加到子控件集合。

我的问题是 - 适当的地方在哪里 - 查看后面的代码或查看模型?前者相对容易,但在我看来打破了模式,但我对如何在视图模型中实现它感到困惑。序列需要

  • 用户选择新日期(日历控件)
  • 处理所选日期更改事件
  • 清除Stackpanel子控件
  • 从db中检索新日期的潜水列表,并为每个
  • 生成用户控件
  • 将用户控件添加为stackpanel子控件。

我想我要问的是 - 有没有办法将子控件集合绑定到视图模型中的对象集合,以便它动态响应 - 这是一种明智的方法吗?

1 个答案:

答案 0 :(得分:1)

执行此操作的适当方法是将StackPanel包裹在ItemsControl中,并将ItemsSource绑定到所选日期的Dives。更改DivesOfThatDay时(确保实现INotifyChanged或DependencyProperty,或使用ObservableCollection),将自动生成每个条目。

<ItemsControl ItemsSource="{Binding DivesOfThatDay}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Vertical"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type Dive}">
            <!-- Your Template -->
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

在MVVM中,您应始终避免在Code-Behind中生成控件。您的View应该从ViewModel获取数据并自行完成 - 否则MVVM会变得毫无用处。在你的情况下它应该这样工作:

  1. 用户在视图
  2. 中选择新日期
  3. 由于视图中的日期控件绑定到 viewmodel 中的某个属性,因此该属性会更新。
  4. viewmodel 通过清除当前的潜水集合并获取新的潜水对此更改作出反应。
  5. 模型数据(来自数据库)封装在 viewmodel (a Dive)中,并添加到 viewmodel中的潜水集合中
  6. 视图ItemsControl)会收到有关此更改的通知(通过INotifyPropertyChangedINotifyCollectionChanged或其他)并告知其ItemContainerGenerator更新控件。
  7. ItemsContainerGenerator为 viewmodel 中的每个Dive生成视图,并将其添加到堆叠面板。
  8. 或简称V→VM→M→VM→V