![](/img/trans.png)
[英]How to bind an ObservableCollection to TreeView (hierarchical)
[英]How to filter treeview with ObservableCollection data
我做了一个 treeview 示例,并希望获得如下所示的结果:
有一组复选框(绿色、黄色和红色)正在被选中。 然后,有一个 treeview。如您所见,如果其中一个子节点包含红色/黄色,则它们的父节点也转向相同的颜色节点。 例如,Class A 节点是红色的,因为 Student 3 它的节点是红色的。
如何在WPF c#中实现过滤树视图function?
示例结果,
如果我取消选中绿色复选框,结果将是:
如果我取消选中绿色和黄色,结果将是:
可以在这里获取 treeview 样本
主 Window XAML
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Vertical">
<CheckBox Content="Green" Margin="2" />
<CheckBox Content="Yellow" Margin="2" />
<CheckBox Content="Red" Margin="2" IsChecked="True" />
</StackPanel>
<TreeView ItemsSource="{Binding ClassList}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type loc:Class}" ItemsSource="{Binding Students}">
<Border Width="150" BorderThickness="1" CornerRadius="2" Margin="2" Padding="2" >
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding Name}" FontWeight="Bold"></TextBlock>
<Image Margin="2" Source="{Binding ImagePath}"></Image>
</StackPanel>
</Border>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type loc:Student}">
<Border Width="132" CornerRadius="2" Margin="1" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="26"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Margin="2" Text="{Binding Name}" ToolTip="{Binding ToolTip}"></TextBlock>
<Image Grid.Column="1" Margin="2" Source="{Binding ImagePath}"></Image>
</Grid>
</Border>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</StackPanel>
因此,您需要跟踪两个集合-一个是“过滤的” ObservableCollcetion,另一个是“主”的ObservableCollection(具有COMPLETE树)。
因此,无论何时绑定到TreeView的ItemsSource,都需要绑定到FilteredObservableCollection。 默认情况下,将使用MasterObservableCollection中的所有项目初始化此集合。
当某人更改Checkbox(并且其绑定反映在您的ViewModel中,即IsRed = false)时,您会在ViewModel上进行一些操作来更新FilteredObservableCollection。 您将清除FilteredObservableCollection中的所有项目,然后遍历MasterObservableCollection,将符合条件的项目添加到其中。
因此,您的ViewModel提供了一些简短的伪代码...
ObservableCollection<MyItem> MasterCollection;
ObservableCollection<MyItem> FilteredCollection;
bool IsRed, IsYellow, IsGreen;
UpdateFilteredCollection()
{
FilteredCollection.Clear();
foreach( MyItem item in MasterCollection )
{
if( ( item.Color == Green && IsGreen ) || ( item.Color == Yellow && IsYellow ) || ( item.Color == Red && IsRed ) )
{
FilteredCollection.Add( item );
/*
And do this for child items, etc -- you'll probably
have to rebuild the tree/MyItem's since some items
will not appear under their parents;
So this might look more like:
FilteredCollection.Add( new MyItem()
{
Color = item.Color,
Label = item.Label
} );
*/
}
}
}
可以为 treeview 层次结构的所有节点设置过滤谓词。 下面我提供了一个扩展方法,您可以调用它来设置过滤器 function,如下所示: myTreeView.Filter(FilterPredicate);
. 当然在过滤谓词中你需要区分你的分层数据model的不同类型的treeview节点。
您的谓词可能如下所示:
private bool FilterPredicate(object node) {
if (node is Students) {
return true; // always show nodes of level 0
}
else if (node is Student) {
return (node as Student).Name.StartsWith(_searchText);
}
return true;
}
这是 TreeViewItem 上的扩展方法,用于递归地在层次结构的所有 TreeViewItems 上设置过滤器:
public static class TreeViewExtensions {
/// <summary>
/// Applies a search filter to all items of a TreeView recursively
/// </summary>
public static void Filter(this TreeView self, Predicate<object> predicate)
{
ICollectionView view = CollectionViewSource.GetDefaultView(self.ItemsSource);
if (view == null)
return;
view.Filter = predicate;
foreach (var obj in self.Items) {
var item = self.ItemContainerGenerator.ContainerFromItem(obj) as TreeViewItem;
FilterRecursively(self, item, predicate);
}
}
private static void FilterRecursively(TreeView tree, TreeViewItem item, Predicate<object> predicate)
{
ICollectionView view = CollectionViewSource.GetDefaultView(item.ItemsSource);
if (view == null)
return;
view.Filter = predicate;
foreach (var obj in item.Items) {
var childItem = tree.ItemContainerGenerator.ContainerFromItem(obj) as TreeViewItem;
FilterRecursively(tree, childItem, predicate);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.