我是WPF世界的新手,我正在尝试根据MVVM设计模式实现应用程序。我在使用树视图方面遇到了一些问题。
我的模型是一个日志消息列表(来自不同的应用程序),具有以下属性:消息,严重性,应用程序。我有一个集合,包含6个属于两个不同应用程序的项目。我希望我的树视图看起来如下:
App A
错误
第一条错误消息(aaa)
第二条错误信息(bbb)
警告
第一条警告信息(ccc)
App B
警告
第一条警告信息(ddd)
信息
第一条信息消息(eee)
第二条信息消息(fff)
我目前的理解是期望有一个带有子列表的项目,所以为了创建我想要的视图,我需要创建一个包含字符串(应用程序名称)和子列表的列表(不同的严重程度)将包含子项列表(显示消息)。
这对我没有意义,因为我在我的View和我的Model之间创建了一个依赖关系,让我们说将来我需要添加另一个层次结构层,我需要更改我的数据结构才能支持它
有没有办法只使用一个具有不同分组的列表?
感谢。
答案 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>
答案 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
层次结构的翻译层,而不是经历这种麻烦,但是,如果您的严重性级别可能会发生变化,这可能是更好的选择。
某些商业数据网格解决方案为嵌套分组提供了相当大的灵活性,但是,我没有足够的经验来推荐这些解决方案。