Элемент фильтра WPF TreeView в HierarchicalDataTemplate - PullRequest
0 голосов
/ 07 мая 2019

Я реализовал простой пример, где TreeView фильтруется с CollectionViewSource.Но как искать во вложенных узлах?Как реализовать фильтрацию во вложенных узлах?

Например, если в textbox будет France, он будет искать во вложенной ноте и возвращать Францию.

enter image description here

MainWindow.xaml

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition Height="30"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Text="{Binding SearchPattern, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
            <I:Interaction.Triggers>
                <I:EventTrigger EventName="TextChanged">
                    <command:EventToCommand Command="{Binding TextChangedCommand}" ></command:EventToCommand>
                </I:EventTrigger>
            </I:Interaction.Triggers>
        </TextBox>
        <TreeView Grid.Row="1" ItemsSource="{Binding YourFilteredCollection}" >
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Path=Nodes}">
                    <TextBlock Text="{Binding Name}" />
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
        <Button Grid.Row="2">Start</Button>
    </Grid>

FooViewModel.cs

public class FooViewModel
    {
        FooModel model = new FooModel();

        private string searchPattern = string.Empty;

        public string SearchPattern
        {
            get
            {
                return searchPattern;
            }

            set
            {
                searchPattern = value;
            }
        }

        private bool UserFilter(object item)
        {
            return (item as Node).Name.Contains(SearchPattern);
        }

        public ICollectionView YourFilteredCollection
        {
            get
            {
                var source = CollectionViewSource.GetDefaultView(model.Items);
                source.Filter = UserFilter;
                return source;
            }
        }

        public ICommand TextChangedCommand
        {
            get
            {
                return new RelayCommand(() => YourFilteredCollection.Refresh());
            }
        }
    }

FooModel.cs

 public class Node
    {
        public string Name { get; set; }

        public ObservableCollection<Node> Nodes { get; set; }
    }

    public class FooModel
    {
        public ObservableCollection<Node> Items { get; set; }

        Random rnd = new Random();

        public FooModel()
        {
            Items = new ObservableCollection<Node>
        {
            new Node
            {
                Name ="Europe",
                Nodes = new ObservableCollection<Node>
                {
                    new Node {Name="Germany" },
                    new Node {Name="France" },
                    new Node
                    {
                        Name ="Great Britain",
                        Nodes = new ObservableCollection<Node>
                        {
                            new Node {Name="England" },
                            new Node {Name="Scotland" },
                            new Node {Name="Wales" },
                            new Node {Name="North Ireland" },
                        }
                    }
                }
            },
            new Node
            {
                Name ="Asia",
                Nodes = new ObservableCollection<Node>
                {
                    new Node {Name="China" },
                    new Node {Name="Japan" },
                    new Node { Name ="India" }
                }
            },
            new Node { Name="Afrika" },
            new Node { Name="USA" },
            new Node { Name="Australia" }
        };
        }
    }

1 Ответ

0 голосов
/ 07 мая 2019

Вам необходимо реализовать рекурсию , то, что может вызвать само себя, чтобы добраться до многих уровней в глубине дерева.Примерно так:

private ObservableCollection<ObservableCollection<Node>> FindCollection(ObservableCollection<Node> collection, ObservableCollection<ObservableCollection<Node>> retVal){
    foreach ( Nodes node in collection){
        if (node.Nodes.Count > 0){
            collectionToCheck = node.Nodes;
            FindCollection(collectionToCheck,retVal);
        }
        if ( node.Name == SearchPattern ){
            retval.Add(collection);
            break;
        }
    }
    return retVal;
}

Вы вызываете подпрограмму, чтобы получить коллекцию, которой принадлежит имя, затем можете связать ее с сеткой или сделать с ней что-нибудь еще необходимое.

public void ApplyFilter(){
    ObservableCollection<ObservableCollection<Node>> collection = FindCollection(Items,new ObservableCollection<ObservableCollection<Node>());

    foreach(ObservableCollection<Node> nodeCollection in collection){
         //...iterate over the node collection that contained the filtered item
    }
}

Есть много способов реализации рекурсии, я не говорю, что это лучший, но это пример того, как мне это нужно было с одной из моих программ, и, по крайней мере, предоставляет пример, чтобы помочь вам добраться доправильное место.Взять код за чистую монету, я попытался описать, как я его реализовал, используя ваш пример.Возможно, вам придется настроить его для ваших обстоятельств.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...