2

I have a treeview that has a hierarchical data. I'd like to add a filter to it so, I could search any element up to n-level. To do that, I find the concept of nested collectionviewsource interesting. But I'm not sure how it will programmatically work.

Suppose we have a Collection of groups and each group has a collection of elements. So, how do I write a nested collectionviewsource so, I could filter the search result of all the elements in all groups?

Here's a sample code that I thought it should work but it only filters the data on the first level and does not goes down to search 'Elements'. So, I wonder how do I write a right nested collectionviewsource to filter the hierarchical data in a treeview.

<UserControl.Resources>
    <CollectionViewSource x:Key="CollectionViewSourceGroups" x:Name="_CollectionViewSourceGroups" Source="{Binding Groups}" Filter="_filterGroups"/>
    <CollectionViewSource x:Key="CollectionViewSourceElements" x:Name="_CollectionViewSourceElements"  Source="{Binding Elements, Source={StaticResource CollectionViewSourceGroups}}" Filter="_filterElements"/>
</UserControl.Resources>

Here's the code that would trigger the filter command:

var cvs = TryFindResource("CollectionViewSourceGroups") as CollectionViewSource;
if (cvs != null)
{
    if (cvs.View != null)
        cvs.View.Refresh();
}
cvs = TryFindResource("CollectionViewSourceElements") as CollectionViewSource;
if (cvs != null)
{
    if (cvs.View != null)
        cvs.View.Refresh();
}

Edit: Here's the sample MVVM and XAML code:

/// <summary>
/// Group of Views
/// </summary>
public class ViewGroup : INotifyPropertyChanged
{
    public string Name { get; set; }
    public List<ViewGroup> Groups { get; set; }


    private List<ProjectObject> _elements;
    public List<ProjectObject> Elements
    {
        get { return _elements; }
        set
        {
            _elements = value;
            OnPropertyChanged();

        }
    }

    public ViewGroup()
    {
        Groups = new List<ViewGroup>();
        Elements = new List<ProjectObject>();
    }

    public event PropertyChangedEventHandler PropertyChanged;
    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class SheetManagerViewModel
{
    public static SheetManagerViewModel Instance;      
    public ObservableCollection<ViewGroup> Groups { get; set; }

    public SheetManagerViewModel()
    {
        Instance = this;
        Groups = new ObservableCollection<ViewGroup>();            
    }
}

<Grid Grid.Row="1">
    <Grid>
        <TreeView  x:Name="ProjectBrowserTreeView" ItemsSource="{Binding Groups}"  MouseMove="ProjectBrowserTreeView_OnMouseMove" DragOver="ProjectBrowserTreeView_OnDragOver" >

            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Groups}" DataType="{x:Type local:ViewGroup}">
                    <Label Content="{Binding Name}"/>
                    <HierarchicalDataTemplate.ItemTemplate>
                        <HierarchicalDataTemplate ItemsSource="{Binding Elements}" DataType="{x:Type local:ViewGroup}">
                            <Label Content="{Binding Name}"/>
                            <HierarchicalDataTemplate.ItemTemplate>
                                <DataTemplate DataType="{x:Type local:ProjectObject}">
                                    <Label Content="{Binding Name}"/>

                                </DataTemplate>
                            </HierarchicalDataTemplate.ItemTemplate>
                        </HierarchicalDataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>
</Grid>
Ali Asad
  • 1,235
  • 1
  • 18
  • 33
  • The TreeView should be bound to a single CollectionViewSource. What's the structure of your data? – mm8 Apr 16 '18 at 09:12
  • The structure is simple, I have a class name ViewGroup.cs. Which has a List Elements and List. Groups. – Ali Asad Apr 16 '18 at 09:36
  • @mm8 can you explain, how to filter hierarchical treeview data with a single collectionviewsource ? – Ali Asad Apr 16 '18 at 09:38
  • I think I'm filtering the root collection. – Ali Asad Apr 16 '18 at 09:39
  • Please always provide a MCVE when asking a question: https://stackoverflow.com/help/mcve – mm8 Apr 16 '18 at 09:40
  • 1
    You can put a collectionviewsource in the hierarchicaldatatemplate or you could bind to a collectionview exposed from a viewmodel and filter that in the viewmodel. – Andy Apr 16 '18 at 09:42
  • Okay, I'll update the question so we have a MCVE for a better conversation. – Ali Asad Apr 16 '18 at 09:42
  • isn't there any way to filter the hierarchical data through a nested collectionviewsource? – Ali Asad Apr 16 '18 at 09:44
  • @mm8 the code is now updated. Please see the edit section in the question above. Let me know what do you think of it? – Ali Asad Apr 16 '18 at 09:59
  • What is ProjectObject and where do you populate the collections? This doesn't seems to be a MCVE. – mm8 Apr 16 '18 at 10:09
  • @mm8 take it as an example, because the complete code is too much. The idea here is how can we filter the hierarchical data in treeview via nested CollectionViewSource. appreciate if there is any solution you could think of. – Ali Asad Apr 16 '18 at 10:16
  • @mm8 you may consider the ProjectObject.cs has only one string property 'Name'. – Ali Asad Apr 16 '18 at 10:17

0 Answers0