-1

I works in c# and have a class that fills a TreeView in Wpf, my problems is that i can't filter del path depending on the elements, I enter a textbox

This is how it currently works for me

This is how it currently works for me

And this is how I need it to come out when entering the value in the textbox

And this is how I need it to come out when entering the value in the textbox

public class ItemProvider
{
    public List<Item> GetItems(string path)
    {
        var items = new List<Item>();
        var dirInfo = new DirectoryInfo(path);

        foreach (var directory in dirInfo.GetDirectories())
        {
            var item = new DirectoryItem
            {
                Name = directory.Name,
                Path = directory.FullName,
                Items = GetItems(directory.FullName)
            };

            items.Add(item);
        }

        foreach (var file in dirInfo.GetFiles())
        {
            var item = new FileItem
            {
                Name = file.Name,
                Path = file.FullName
            };

            items.Add(item);
        }

        return items;
    }
}
5
  • Images are not loaded in your question.. Commented Sep 8, 2022 at 12:53
  • Thanks for letting me know, they are already loaded correctly @Muhammad Sulaiman Commented Sep 8, 2022 at 13:01
  • Can you post code around how you are passing the items to the TreeView? Commented Sep 8, 2022 at 14:46
  • You need to only filter files right? Since you are using Item class for both files and folders, you might wanna add a flag, something like bool IsFile or something to be able to apply the filter only to files. Commented Sep 8, 2022 at 14:49
  • The original code is link @Andrew KeepCoding Commented Sep 8, 2022 at 14:54

1 Answer 1

0

This is how I'd implement this. (Actually, implemented for this answer.)

I'm using the CommunityToolkit.Mvvm NuGet package to implement the MVVM design.

ItemProvider.cs

using System.Collections.Generic;

namespace WpfAppTreeViewTest;

public class Item
{
    public string Name { get; set; }
    public string Path { get; set; }
}

public class FileItem : Item
{
}

public class DirectoryItem : Item
{
    public List<Item> Items { get; set; }

    public DirectoryItem()
    {
        Items = new List<Item>();
    }
}

public class ItemProvider
{
    public List<Item> GetItems(string path)
    {
        return new List<Item>()
        {
            new DirectoryItem()
            {
                Name = "comedy",
                Items = new List<Item>()
                {
                    new FileItem() { Name = "1001.PDF" },
                    new FileItem() { Name = "1002.PDF" },
                    new FileItem() { Name = "1003.PDF" },
                },
            },
            new DirectoryItem()
            {
                Name = "horror",
                Items = new List<Item>()
                {
                    new FileItem() { Name = "1005.PDF" },
                    new FileItem() { Name = "1006.PDF" },
                },
            },
            new DirectoryItem()
            {
                Name = "suspense",
                Items = new List<Item>()
                {
                    new FileItem() { Name = "1002.PDF" },
                    new FileItem() { Name = "1005.PDF" },
                    new FileItem() { Name = "1006.PDF" },
                },
            },
        };
    }
}

MainWindowViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.Generic;
using System.Linq;

namespace WpfAppTreeViewTest;
// This class needs to be partial for the CommunityToolkit's source generators.
public partial class MainWindowViewModel : ObservableObject
{
    // The source generators will auto-create a "FilterText" property.
    [ObservableProperty]
    private string filterText = string.Empty;

    // The source generators will auto-create a "FilteredItems" property.
    [ObservableProperty]
    private IEnumerable<Item>? filteredItems;

    private List<Item>? items;

    public MainWindowViewModel()
    {
        var itemProvider = new ItemProvider();
        this.items = itemProvider.GetItems("");
        FilteredItems = this.items;
    }

    // This is a "partial" method created by the source generator.
    // This method will be called everytime "FilterText" changes.
    partial void OnFilterTextChanged(string value)
    {
        FilteredItems = this.items?
            .OfType<DirectoryItem>()
            .Select(d => new DirectoryItem()
            {
                Name = d.Name,
                Path = d.Path,
                Items = d.Items.Where(x => x.Name.Contains(value)).ToList(),
            })
            .Where(x => x.Items.Any() is true);
    }
}

MainWindow.cs

using System.Windows;
using System.Windows.Controls;

namespace WpfAppTreeViewTest;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    public MainWindowViewModel ViewModel { get; } = new();
}

MainWindow.xaml

<Window
    x:Class="WpfAppTreeViewTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:WpfAppTreeViewTest"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    x:Name="ThisWindow"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <StackPanel>
        <StackPanel.Resources>
            <HierarchicalDataTemplate
                DataType="{x:Type local:DirectoryItem}"
                ItemsSource="{Binding Items}">
                <TextBlock
                    Text="{Binding Path=Name}"
                    ToolTip="{Binding Path=Path}" />
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type local:FileItem}">
                <TextBlock
                    Text="{Binding Path=Name}"
                    ToolTip="{Binding Path=Path}" />
            </DataTemplate>
        </StackPanel.Resources>
        <TextBox Text="{Binding ElementName=ThisWindow, Path=ViewModel.FilterText, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" />
        <TreeView ItemsSource="{Binding ElementName=ThisWindow, Path=ViewModel.FilteredItems}">
            <TreeView.Resources>
                <Style TargetType="TreeViewItem">
                    <Setter Property="IsExpanded" Value="True" />
                </Style>
            </TreeView.Resources>
        </TreeView>
    </StackPanel>
</Window>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.