使用MVVM嵌套动态内容控件

时间:2016-04-26 09:20:38

标签: c# wpf mvvm

我有兴趣创建一个嵌套内容控件系统,以直观地表示自动化系统中用户创建的节点网络。

简单地说,我有节点'x',它们每个都包含主机通道'z'的模块'y'。

到目前为止,我已经在ViewModel中设置了一个用于实例化所有这一切的系统。 我有x其中List<y>是一个包含y的模型(以及属性:name,ID), 其中List<z>是包含z的模型(以及属性:name,index),其中x是通道的模型(属性:名称,状态,命令)。

我现在想在我的视图中显示这些内容。

我想这样做的方式如下,对于List<x>中的每个模型List<y>,应该有一个Headered Content Control(或其他控件),其item-source是{{ 1}}在此模型x中。内容控制还应显示x的“名称”属性。

此内容控件下每个y的数据窗口应该是一个类似的内容控件,其中item-source是此模型List<z>中的y。内容控制还应显示y的“名称”属性。

最后,此内容控件下的每个模型z都应显示为CheckBox,将其“缺陷”状态绑定到模型的“state”属性,它的内容为“name”属性,它是命令到'command'属性。

我的问题是;有没有办法在MVVM中做到这一点?如果是这样,我将如何设置它?

1 个答案:

答案 0 :(得分:0)

像往常一样,有几种方法可以完成这项任务。它很大程度上取决于你想要达到的视觉效果。

您可以将数据显示为树:

<TreeView ItemsSource="{Binding Nodes}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:Node}"
                                  ItemsSource="{Binding Modules}">
            <TextBlock Text="{Binding Name}" />
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate DataType="{x:Type local:Module}"
                                  ItemsSource="{Binding Channels}">
            <TextBlock Text="{Binding Name}" />
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type local:Channel}">
            <CheckBox Content="{Binding Name}"
                      IsChecked="{Binding State}"
                      Command="{Binding Command}" />
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

在此示例中,类的嵌套项的外观和关系由HierarchicalDataTemplate定义。 TreeView控制是“聪明”的,足以知道如何处理这些。

更一般的解决方案将是这样的:

<ItemsControl ItemsSource="{Binding Nodes}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <HeaderedContentControl Header="{Binding Name}">
                <ItemsControl ItemsSource="{Binding Modules}"
                              Margin="10,0,0,0">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <HeaderedContentControl Header="{Binding Name}">
                                <ItemsControl ItemsSource="{Binding Channels}"
                                              Margin="10,0,0,0">
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <CheckBox IsChecked="{Binding State}"
                                                      Content="{Binding Name}"
                                                      Command="{Binding Command}" />
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>
                            </HeaderedContentControl>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </HeaderedContentControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

此处,每个类的模板由相应ItemTemplate上的ItemsControl属性明确定义。我使用Margin属性来嵌套项目来引入一些缩进。

注意

为了便于阅读,我分别将xyz类名替换为NodeModuleChannel 。另外,我使用了相应的集合名称 - NodesModulesChannels - 我认为这些名称应该是不言自明的。