Help to filter in TreeView

sblb 1,231 Reputation points
2024-11-06T20:32:35.2633333+00:00

Hi, I've a blazor hybrid maui application and I have put the treeview.

I have created a service to search for files in the tree structure and a text input for the search. My problem is that when I select a file in the search zone the nodes are filtered where the file is located but I also see the other files in this directory;

do you have any idea where I made the mistake or did I forget something? thank you for your help.

Structure of the treeview before the searching

User's image

Structure of the treeview after the search

User's image

Hereafter the method

public async Task<List<FileNode>> SearchTreeNodesAsync(List<FileNode> nodes, string searchTerm, List<string> debugMessages)
{
    // Effacez les anciens messages de débogage avant chaque recherche
    debugMessages.Clear();
    debugMessages.Add($"Début de la recherche pour le terme : {searchTerm}");

    if (string.IsNullOrWhiteSpace(searchTerm))
    {
        debugMessages.Add("Le terme de recherche est vide, retour de tous les nœuds.");
        return nodes;
    }

    var result = new List<FileNode>();

    foreach (var node in nodes)
    {
        debugMessages.Add($"Recherche dans le nœud : {node.Name}");

        // Vérifie si le nom du nœud contient le terme de recherche
        bool isMatch = node.Name.Contains(searchTerm, StringComparison.OrdinalIgnoreCase);

        if (isMatch)
        {
            debugMessages.Add($"Correspondance trouvée : {node.Name}");

            // Si le nœud correspond, ajoute-le directement au résultat sans enfants
            result.Add(new FileNode
            {
                Name = node.Name,
                Path = node.Path,
                IsDirectory = node.IsDirectory,
                Children = new List<FileNode>() // Pas besoin de charger les enfants ici
            });
        }
        else if (node.IsDirectory)
        {
            debugMessages.Add($"Le nœud {node.Name} est un dossier, chargement des enfants...");

            // Charge dynamiquement les enfants si nécessaire
            if (node.Children == null || node.Children.Count == 0)
            {
                node.Children = await LoadSubdirectoriesAsync(node.Path);
                node.Children.AddRange(await LoadDirectoryAsync(node.Path));
                debugMessages.Add($"Enfants chargés pour le dossier : {node.Name}, Nombre d'enfants : {node.Children.Count}");
            }

            // Recherche parmi les enfants du dossier
            var filteredChildren = await SearchTreeNodesAsync(node.Children, searchTerm, debugMessages);
            if (filteredChildren.Count > 0)
            {
                debugMessages.Add($"Des enfants correspondent au terme de recherche dans le dossier : {node.Name}");

                // Crée un nouveau dossier avec uniquement les enfants correspondants
                result.Add(new FileNode
                {
                    Name = node.Name,
                    Path = node.Path,
                    IsDirectory = true,
                    Children = filteredChildren // Ajoute uniquement les enfants qui correspondent
                });
            }
            else
            {
                debugMessages.Add($"Aucun enfant correspondant trouvé dans le dossier : {node.Name}");
            }
        }
    }

    debugMessages.Add($"Recherche terminée, nombre de résultats trouvés : {result.Count}");
    return result;
}

razor page

  private async Task SearchInTree(int treeNumber)
  {
      switch (treeNumber)
      {
          case 1:
              // Utilisez le debugMessages pour capturer chaque étape de la recherche
              filteredTree1 = await FileService.SearchTreeNodesAsync(tree1, searchTerm1, debugMessages);
              if (!filteredTree1.Any())
              {
                  debugMessages.Add("Aucun résultat trouvé.");
              }
              else
              {
                  debugMessages.Add($"{filteredTree1.Count} résultat(s) trouvé(s)");
              }       
        break;           
       } 
      StateHasChanged();    
}

Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,596 questions
{count} votes

1 answer

Sort by: Most helpful
  1. sblb 1,231 Reputation points
    2024-11-07T10:14:16.8833333+00:00

    I'm sharing FileMangerService.cs and the Razor page with you.

    FileMangerService.cs

    
    
    namespace MauiAppDTClassLibrary.ServicesApi.ArchivageService
    {
       public class FileNode
    {
        public string Name { get; set; }
        public string Path { get; set; }
        public bool IsDirectory { get; set; }
         public List<FileNode> Children { get; set; } = new List<FileNode>();
    
        }
    
    public class FileManagerService
        {
            public async Task<List<FileNode>> LoadDirectoryAsync(string path, int page = 1, int pageSize = 50)
            {
                var nodes = new List<FileNode>();
    
                // Charger les répertoires
                var directories = Directory.GetDirectories(path)
                                           .Skip((page - 1) * pageSize)
                                           .Take(pageSize)
                                           .Select(dir => new FileNode
                                           {
                                               Name = Path.GetFileName(dir),
                                               Path = dir,
                                               IsDirectory = true
                                           });
                foreach (var dir in directories)
                {
                    nodes.Add(dir);
                }
    
                // Charger les fichiers
                var files = Directory.GetFiles(path)
                                     .Skip((page - 1) * pageSize)
                                     .Take(pageSize)
                                     .Select(file => new FileNode
                                     {
                                         Name = Path.GetFileName(file),
                                         Path = file,
                                         IsDirectory = false
                                     });
                foreach (var file in files)
                {
                    nodes.Add(file);
                }
    
                return await Task.FromResult(nodes);
            }
    
            public async Task<List<FileNode>> LoadSubdirectoriesAsync(string path, int page = 1, int pageSize = 50)
            {
                var nodes = new List<FileNode>(
                            Directory.GetDirectories(path)
                                     .Skip((page - 1) * pageSize)
                                     .Take(pageSize)
                                     .Select(dir => new FileNode
                                     {
                                         Name = Path.GetFileName(dir),
                                         Path = dir,
                                         IsDirectory = true
                                     })
                                     ); 
                return await Task.FromResult(nodes);
            }
    
            public async Task<bool> MoveFileOrDirectoryAsync(string sourcePath, string targetPath)
            {
                try
                {
                    // Si targetPath est un dossier, combinez avec le nom du fichier source
                    string destinationPath = targetPath;
                    if (Directory.Exists(targetPath))
                    {
                        // targetPath est un dossier, donc on ajoute le nom du fichier source
                        var fileName = Path.GetFileName(sourcePath);
                        destinationPath = Path.Combine(targetPath, fileName);
                    }
    
                    // Vérifie si un fichier ou un dossier existe déjà au chemin de destination
                    if (File.Exists(destinationPath) || Directory.Exists(destinationPath))
                    {
                        Console.WriteLine("Le fichier ou répertoire de destination existe déjà : " + destinationPath);
                        return false;
                    }
    
                    // Déplace le fichier ou le dossier
                    if (Directory.Exists(sourcePath))
                    {
                        Directory.Move(sourcePath, destinationPath);
                    }
                    else if (File.Exists(sourcePath))
                    {
                        File.Move(sourcePath, destinationPath);
                    }
                    else
                    {
                        Console.WriteLine("Le fichier ou répertoire source n'existe pas : " + sourcePath);
                        return false;
                    }
    
                    return true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Erreur lors du déplacement : " + ex.Message);
                    return false;
                }
            }
            public async Task<List<FileNode>> SearchTreeNodesAsync(List<FileNode> nodes, string searchTerm, List<string> debugMessages)
            {
                debugMessages.Clear();
                debugMessages.Add($"Début de la recherche pour le terme : {searchTerm}");
    
                if (string.IsNullOrWhiteSpace(searchTerm))
                {
                    debugMessages.Add("Le terme de recherche est vide, retour de tous les nœuds.");
                    return nodes;
                }
    
                var result = new List<FileNode>();
    
                foreach (var node in nodes)
                {
                    debugMessages.Add($"Recherche dans le nœud : {node.Name}");
    
                    bool isMatch = node.Name.Contains(searchTerm, StringComparison.OrdinalIgnoreCase);
    
                    if (isMatch)
                    {
                        debugMessages.Add($"Correspondance trouvée : {node.Name}");
    
                        result.Add(new FileNode
                        {
                            Name = node.Name,
                            Path = node.Path,
                            IsDirectory = node.IsDirectory,
                            Children = new List<FileNode>()
                        });
                    }
                    else if (node.IsDirectory)
                    {
                        debugMessages.Add($"Le nœud {node.Name} est un dossier, chargement des enfants...");
    
                        if (node.Children == null || node.Children.Count == 0)
                        {
                            node.Children = await LoadSubdirectoriesAsync(node.Path);
                            node.Children.AddRange(await LoadDirectoryAsync(node.Path));
                            debugMessages.Add($"Enfants chargés pour le dossier : {node.Name}, Nombre d'enfants : {node.Children.Count}");
                        }
    
                        var filteredChildren = await SearchTreeNodesAsync(node.Children, searchTerm, debugMessages);
                        if (filteredChildren.Count > 0)
                        {
                            debugMessages.Add($"Des enfants correspondent au terme de recherche dans le dossier : {node.Name}");
    
                            result.Add(new FileNode
                            {
                                Name = node.Name,
                                Path = node.Path,
                                IsDirectory = true,
                                Children = filteredChildren
                            });
                        }
                        else
                        {
                            debugMessages.Add($"Aucun enfant correspondant trouvé dans le dossier : {node.Name}");
                        }
                    }
                }
    
                debugMessages.Add($"Recherche terminée, nombre de résultats trouvés : {result.Count}");
                return result;
            }
    
    
        }
    }
    
    
    

    Razor pages

        <Card Style="width: 40%;">
            <CardHeader>
                <h4>Répertoire 1</h4>
            </CardHeader>
            <CardBody>
                <TextEdit @bind-Text="searchTerm1" Placeholder="Rechercher..." Style="width: 100%; margin-bottom: 10px;" />
                <Button Size="Size.Small" Color="Color.Primary" IconName="fas fa-search" Clicked="@(() => SearchInTree(1))" Style="margin-bottom: 10px;">Chercher</Button>
                <Button Size="Size.Small" Color="Color.Primary" IconName="fas fa-sync" Clicked="@(() => ReloadTree(1))" Style="margin-bottom: 10px;">Rafraîchir</Button>
                 
                <div class="tree-container">
                    <TreeView TNode="FileNode" Nodes="@filteredTree1"
                              HasChildNodes="@(node => node.IsDirectory)"
                              GetChildNodes="@(node => LoadSubnodesSync(node.Path))"
                              SelectedNodeChanged="OnSelectedNodeChanged1"
                              SelectionMode="TreeViewSelectionMode.Single">
                        <NodeContent> 
                            @if (context.IsDirectory)
                            {
                              <i class="fas fa-folder" style="color: #FFD700; margin-right: 5px;"></i>
                            }
                            else
                            {
                                <input type="checkbox" @onchange="(e => OnNodeCheckedChanged(context, e))" style="margin-right: 5px;" />
                               <i class="fas fa-file" style="color: gray; margin-right: 5px;"></i>
                            }
                            <span>@context.Name</span>                    
                        </NodeContent>
                    </TreeView>
                </div>
            </CardBody>
    
            <CardFooter>
                <div class="d-flex justify-content-between">
                    <Button Size="Size.Small" Color="Color.Primary" Clicked="@(() => ChangePage(1, -1))" Disabled="@(_page1 == 1)">Précédent</Button>
                    <Button Size="Size.Small" Color="Color.Primary" Clicked="@(() => ChangePage(1, 1))">Suivant</Button>
                </div>
            </CardFooter>
        </Card>
    
        <div class="d-flex flex-column justify-content-center gap-2">
            <Button Color="Color.Primary" Size="Size.Small" IconName="fas fa-arrow-right" Clicked="MoveToDirectory2"><i class="fas fa-arrow-right"></i></Button>
            <Button Color="Color.Primary" Size="Size.Small" IconName="fas fa-arrow-left" Clicked="MoveFromDirectory2"><i class="fas fa-arrow-left"></i></Button>
        </div>
    
        <!-- Répertoire 2 -->
        <Card Style="width: 40%;">
            <CardHeader>
                <h4>Répertoire 2</h4>
            </CardHeader>
            <CardBody>
                <TextEdit @bind-Text="searchTerm2" Placeholder="Rechercher..." Style="width: 100%; margin-bottom: 10px;" />
                <Button Size="Size.Small" Color="Color.Primary" IconName="fas fa-sync" Clicked="@(() => ReloadTree(2))" Style="margin-bottom: 10px;">Rafraîchir</Button>
    
                <div class="tree-container">
                    <TreeView TNode="FileNode" Nodes="@filteredTree2"
                              HasChildNodes="@(node => node.IsDirectory)"
                              GetChildNodes="@(node => LoadSubnodesSync(node.Path))"
                              SelectedNodeChanged="OnSelectedNodeChanged2"
                              SelectionMode="TreeViewSelectionMode.Single">
                        <NodeContent>                       
                                    @if (context.IsDirectory)
    
                                    {
                                        <i class="fas fa-folder" style="color: #FFD700; margin-right: 5px;"></i>
                                    }
    
                                    else
    
                                    {
                                        <i class="fas fa-file" style="color: gray; margin-right: 5px;"></i>
                                    }
                                    <span>@context.Name</span>                          
                        </NodeContent>
                    </TreeView>
                </div>
            </CardBody>
            <CardFooter>
                <div class="d-flex justify-content-between">
                    <Button Size="Size.Small" Color="Color.Primary" Clicked="@(() => ChangePage(2, -1))" Disabled="@(_page2 == 1)">Précédent</Button>
                    <Button Size="Size.Small" Color="Color.Primary" Clicked="@(() => ChangePage(2, 1))">Suivant</Button>
                </div>
            </CardFooter>
        </Card>
    
        <div class="d-flex flex-column justify-content-center gap-2">
            <Button Color="Color.Primary" Size="Size.Small" IconName="fas fa-arrow-right" Clicked="MoveToDirectory3"><i class="fas fa-arrow-right"></i></Button>
            <Button Color="Color.Primary" Size="Size.Small" IconName="fas fa-arrow-left" Clicked="MoveFromDirectory3"><i class="fas fa-arrow-left"></i></Button>
        </div>
    
        <!-- Répertoire 3 -->
        <Card Style="width: 40%;">
            <CardHeader>
                <h4>Répertoire 3</h4>
            </CardHeader>
            <CardBody>
                <TextEdit @bind-Text="searchTerm3" Placeholder="Rechercher..." Style="width: 100%; margin-bottom: 10px;" />
                <Button Size="Size.Small" Color="Color.Primary" IconName="fas fa-sync" Clicked="@(() => ReloadTree(3))" Style="margin-bottom: 10px;">Rafraîchir</Button>
                <div class="tree-container">
                    <TreeView TNode="FileNode" Nodes="@filteredTree3"
                              HasChildNodes="@(node => node.IsDirectory)"
                              GetChildNodes="@(node => LoadSubnodesSync(node.Path))"
                              SelectedNodeChanged="OnSelectedNodeChanged3"
                              SelectionMode="TreeViewSelectionMode.Single">
                        <NodeContent>                        
                                    @if (context.IsDirectory)
    
                                    {
                                        <i class="fas fa-folder" style="color: #FFD700; margin-right: 5px;"></i>
                                    }
    
                                    else
    
                                    {
                                        <i class="fas fa-file" style="color: gray; margin-right: 5px;"></i>
                                    }
                                    <span>@context.Name</span>
                             
                        </NodeContent>
                    </TreeView>
                </div>
            </CardBody>
            <CardFooter>
                <div class="d-flex justify-content-between">
                    <Button Size="Size.Small" Color="Color.Primary" Clicked="@(() => ChangePage(3, -1))" Disabled="@(_page3 == 1)">Précédent</Button>
                    <Button Size="Size.Small" Color="Color.Primary" Clicked="@(() => ChangePage(3, 1))">Suivant</Button>
                </div>
            </CardFooter>
        </Card>
    </div>
    
    @if (statusMessage != null)
    
    {
        <div class="alert alert-danger mt-3">@statusMessage</div>
    }
    
    <div>
        <h5>Messages de Débogage</h5>
        <ul>
            @foreach (var message in debugMessages)
    
            {
                <li>@message</li>
            }
        </ul>
    </div>
    
    @code {
        private List<string> debugMessages = new(); // Liste des messages de débogage  
        private string searchTerm1 = string.Empty;
        private string? statusMessage = null;     
        private List<FileNode> selectedFiles = new();    
        private string? searchResultMessage1 = null;          
        private List<FileNode> tree1 = new();     
     
           
        private List<FileNode> filteredTree1 = new();    
                  
          private int _page1 = 1; 
          private string  rootDireectroyPrelimianire = @"C:\\App\\rep_test_à_supprimer\\SMS_PRELIMINAIRE";
        private string rootDirectroySerie = @"C:\\App\\rep_test_à_supprimer\\ARTICLE";
        private string rootDireectroyHistorique = @"C:\\App\\rep_test_à_supprimer\\Historique";
    
    
        protected override async Task OnInitializedAsync()
        {
            await ReloadTree(1);
    
    
            // Initialise les vues filtrées avec tous les éléments
            filteredTree1 = tree1;
    
        }
    
        private void OnNodeCheckedChanged(FileNode node, ChangeEventArgs e)
        {
            if ((bool)e.Value)
            {
                // Ajoute le fichier à la liste des fichiers sélectionnés
                selectedFiles.Add(node);
            }
            else
            {
                // Retire 
                selectedFiles.Remove(node);
            }
        }
    
        private List<FileNode> LoadSubnodesSync(string path, int page = 1, int pageSize = 50)
        {
            try
            {
                var nodes = new List<FileNode>(FileService.LoadDirectoryAsync(path, page, pageSize).Result);
                return nodes;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Erreur lors du chargement des sous-nœuds : {ex.Message}");
                return new List<FileNode>();
            }
        }
    
        private async Task ReloadTree(int treeNumber, int page = 1)
    
        {
            switch (treeNumber)
            {
                case 1:
                    tree1 = await FileService.LoadDirectoryAsync(rootDireectroyPrelimianire,page);
                    filteredTree1 = new List<FileNode>(tree1);
                    searchResultMessage1 = null;
                    break;
                                     
           }     }     
    
    
    
     private async Task SearchInTree(int treeNumber)
        {
            switch (treeNumber)
            {
                case 1:
                    // Utilisez 
                    filteredTree1 = await FileService.SearchTreeNodesAsync(tree1, searchTerm1, debugMessages);
                    if (!filteredTree1.Any())
                    {
                        debugMessages.Add("Aucun résultat trouvé.");
                    }
                    else
                    {
                        debugMessages.Add($"{filteredTree1.Count} résultat(s) trouvé(s)");
                    }
                    break;
            }
            StateHasChanged();
    
        }
    
        private void OnSelectedNodeChanged1(FileNode node)
        {  
            selectedNode1 = node;
        }
    
    
        
    }
    
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.