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;
}
}