[英]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.