使用不同的源分组树视图

时间:2011-03-28 17:28:00

标签: wpf mvvm treeview binding

我是WPF世界的新手,我正在尝试根据MVVM设计模式实现应用程序。我在使用树视图方面遇到了一些问题。

我的模型是一个日志消息列表(来自不同的应用程序),具有以下属性:消息,严重性,应用程序。我有一个集合,包含6个属于两个不同应用程序的项目。我希望我的树视图看起来如下:

App A
错误
第一条错误消息(aaa)
第二条错误信息(bbb)
警告
第一条警告信息(ccc)
App B
警告
第一条警告信息(ddd)
信息
第一条信息消息(eee)
第二条信息消息(fff)

我目前的理解是期望有一个带有子列表的项目,所以为了创建我想要的视图,我需要创建一个包含字符串(应用程序名称)和子列表的列表(不同的严重程度)将包含子项列表(显示消息)。

这对我没有意义,因为我在我的View和我的Model之间创建了一个依赖关系,让我们说将来我需要添加另一个层次结构层,我需要更改我的数据结构才能支持它

有没有办法只使用一个具有不同分组的列表?

感谢。

2 个答案:

答案 0 :(得分:3)

您可以轻松地使用CollectionView对数据进行分组,即使是以嵌套方式:

ObservableCollection<LogEntry> data = new ObservableCollection<LogEntry>(new LogEntry[]
{
    new LogEntry("App1", "Warning", "Msg1"),
    new LogEntry("App1", "Error", "Msg2"),
    new LogEntry("App1", "Warning", "Msg3"),
    new LogEntry("App2", "Error", "Msg4"),
    new LogEntry("App2", "Info", "Msg5"),
    new LogEntry("App2", "Info", "Msg6"),
});
ListCollectionView view = (ListCollectionView)CollectionViewSource.GetDefaultView(data);
view.GroupDescriptions.Add(new PropertyGroupDescription("Application"));
view.GroupDescriptions.Add(new PropertyGroupDescription("Severity"));
Data = view;

(你也可以在XAML中创建CollectionView视图,这只是一个例子)

现在您可以使用DataTemlates显示它:

<TreeView ItemsSource="{Binding Data.Groups}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type CollectionViewGroup}" ItemsSource="{Binding Items}">
            <TextBlock Text="{Binding Name}"/>
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type local:LogEntry}">
            <TextBlock Text="{Binding Message}"/>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

看起来像这样:
http://i52.tinypic.com/xeeut5.png

答案 1 :(得分:1)

您将不得不在逻辑意义上创建视图,这将创建分层数据模板所需的嵌套。如果我理解正确,您有一个集合,表示您的应用程序收到的日志事件的时间表。

如果您不想更改基本集合(adapted from this post),则可以使用嵌套CollectionViewSource的嵌套TreeView。但是,我不知道这是否会尊重基础集合的在线更新,我决定在数据上下文中是属性Messages

<!-- First level grouping on the application name -->
<CollectionViewSource x:Key="ApplicationGroups"
                      Source="{Binding Messages}">
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="Application" />
    </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

然后为应用程序和严重性级别设置模板:

<HierarchicalDataTemplate x:Key="ApplicationTemplate">
    <!-- Nested tree view for the severity -->
    <TreeView>
        <TreeView.Resources>
            <!-- Since this TreeView will receive a Group as its DataContext
                 we will bind to its Items property, containing the objects
                 which are a member of its group
             -->
            <CollectionViewSource x:Key="SeverityGroups"
                                  Source="{Binding Items}">
                <CollectionViewSource.GroupDescriptions>
                    <PropertyGroupDescription PropertyName="Severity" />
                </CollectionViewSource.GroupDescriptions>
            </CollectionViewSource>

            <!-- Message Template -->
            <DataTemplate x:Key="MessageTemplate">
                <TextBlock Text="{Binding Message}" />
            </DataTemplate>

            <!-- Severity Hierarchy Template -->
            <HierarchicalDataTemplate x:Key="SeverityTemplate"
                                      ItemsSource="{Binding Items}"
                                      ItemsTemplate="{StaticResource MessageTemplate}">
                <TextBlock Text="{Binding Name}" />
            </HierarchicalDataTemplate>
        </TreeView.Resources>

        <!-- Application sub-Tree View -->
        <TreeViewItem Header="{Binding Name}"
                      ItemsSource="{Binding Groups, Source={StaticResource SeverityGroups}}"
                      ItemTemplate="{StaticResource SeverityTemplate}" />
    </TreeView>
</HierarchicalDataTemplate>

然后,您的TreeView将其ItemsSource设置为集合视图的Groups属性,如下所示:

<TreeView ItemsSource="{Binding Groups, Source={StaticResource ApplicationGroups}}"
          ItemTemplate="{StaticResource ApplicationTemplate}" />

通常,我会创建一个转换为自然ViewModel层次结构的翻译层,而不是经历这种麻烦,但是,如果您的严重性级别可能会发生变化,这可能是更好的选择。

某些商业数据网格解决方案为嵌套分组提供了相当大的灵活性,但是,我没有足够的经验来推荐这些解决方案。