15/05/2025 - KronS ha scritto:
Mi sono autolimitato a inserire una immagine diversa a seconda se la riga è un nodo padre o è un nodo figlio. Quindi l'immagine rimane la stessa sia espansa che no
Ora ho capito meglio il tuo intento...
Che dire, le tecniche possono essere diverse.
Personalmente cerco sempre di semplificare e alleggerire il codice quanto più possibile.
Nell'esempio postato in precedenza, mi sono fermato a 3 immagini. Due immagini per la Folder chiusa e aperta e Un immagine per i Files.
Si potrebbe anche utilizzare un immagine diversa sulla base del tipo di file.... Ma in questo caso specifico non ho ritenuto opportuno appesantire il tutto in quanto non sarebbe risultata un esperienza utile per l'utente.
Comunque tutto dipende dagli scenari e, si possono fare diverse cose.
Considerando che attualmente la TreeView contiene più di 33.000 Files e più di 1.600 Cartelle ed è destinata a crescere, ho utilizzato il "metodo Lazy".
Questo metodo consente di avere una visualizzazione e navigazione praticamente istantanea e molto fluida. (tempi di attesa di caricamento praticamente pari a zero)
Se vuoi posso farti vedere come ho approcciato questa TreeView per i file di Backup....
- Lo scopo è quello di visualizzare un elenco di Cartelle e Files che ho mappato in un percorso di rete con la root U:\
- si possono avere una o più Radici. In questo caso ne vediamo una sola.
- si visualizzano tutte le cartelle e i files che vengono salvati come backup. E' previsto di :
- visualizzare i singoli files, le Proprietà e il loro Contenuto
- per visualizzare il contenuto dei files, viene utilizzata la funzione classica di Windows "Apri con" dove si sceglie con quale applicazione aprire il file
- scaricare il file. Selezionado il file con una Open Dialog "Save As" si può decidere di copiare il file di Backup in una cartella a proprio piacimento
:
Caricamento della Treeview:
Caricamento dell'immagini - Folder Chiusa - Folder Aperta - File (document image)
// Set image list for treeview
ImageList imageListTree = new ImageList();
imageListTree.Images.Add("folder", Properties.Resources.DataTreeFolder);
imageListTree.Images.Add("file", Properties.Resources.DataTreeDocument);
imageListTree.Images.Add("folder_open", Properties.Resources.DataTreeFolderOpen);
this.TreeViewBackup.ImageList = imageListTree;
|
Caricamento delle solo Radici... Da una tabella del database si prende la Radice o le Radici che saranno caricate nella TreeView.
Con queste radici si imposta la e/o le Root (primo livello) della TreeView:
// LOAD ROOT BACKUP FOLDER AND LOAD TREEVIEW LAZY METHOD
private void MyGetRootFolderPair()
{
// Clear treeview
this.TreeViewBackup.Nodes.Clear();
// Set connection database string and open
using (SqlConnection connection = new SqlConnection(ClassSetup.cnnString))
{
connection.Open();
// Read pairing table
using (SqlCommand command = new SqlCommand("SELECT DISTINCT PairFolderBackup FROM TblFolderPair;", connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
// Get root pair backup and load treeview
string stringRoot = reader.GetString(reader.GetOrdinal("PairFolderBackup"));
// Add root node with image and tag
TreeNode rootNode = new TreeNode(stringRoot)
{
Tag = stringRoot,
ImageKey = "folder_open",
SelectedImageKey = "folder_open"
};
this.TreeViewBackup.Nodes.Add(rootNode);
// Load folders, subfolders and files - Lazy Method
MyLoadSubDirectoriesLazy(rootNode, stringRoot);
}
}
}
}
}
|
Inizializzazione/Caricamento TreeView con il primo livello Radici Padri Figli
// LOAD TREEVIEW - LAZY METHOD THAT ADDS ONLY THE FIRST-LEVEL DIRECTORIEW AND FILE
private void MyLoadSubDirectoriesLazy(TreeNode parentNode, string path)
{
try
{
// Adds all the first-level directories
foreach (var directory in Directory.GetDirectories(path))
{
// Add root node with image and tag
TreeNode folderNode = new TreeNode(Path.GetFileName(directory))
{
Tag = directory,
ImageKey = "folder",
SelectedImageKey = "folder"
};
folderNode.Nodes.Add("Loading...");
parentNode.Nodes.Add(folderNode);
}
// Adds all files in the folder
foreach (var file in Directory.GetFiles(path))
{
// Add root node with image and tag
TreeNode fileNode = new TreeNode(Path.GetFileName(file))
{
Tag = file,
ImageKey = "file",
SelectedImageKey = "file"
};
parentNode.Nodes.Add(fileNode);
}
}
catch (UnauthorizedAccessException)
{
// Set access denied
parentNode.Nodes.Add(new TreeNode("[Access denied]"));
}
}
|
Caricamento "Lazy" per tutti gli altri nodi padri e figli - metodo ricorsivo per caricare cartelle e file ad ogni richiesta di espansione dei nodi
// TREEVIEW EXPAND FIRST LEVEL - RECORSIVE METHOD
private void MyExpandFirstLevels(TreeNodeCollection nodes, int currentLevel, int maxLevel)
{
if (currentLevel > maxLevel) { return; }
foreach (TreeNode node in nodes)
{
node.Expand();
if (node.Nodes.Count > 0) { MyExpandFirstLevels(node.Nodes, currentLevel + 1, maxLevel); }
}
}
|
Espansione Nodi - Si sfruttano i due eventi "BeforeExpand" e "BeforeCollapse"
All'apertura e chiusura dei Nodi si "cambiano le immagini"
// TREEVIEW - LOAD WITH LAZY METHOD - EVENT THAT ACTUALLY LOADS THE NODES WHEN THEY ARE EXPANDED
private void TreeViewBackup_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
// Retrieve click node select
TreeNode node = e.Node;
// Change image node - folder open
if (Directory.Exists(node.Tag?.ToString() ?? ""))
{
node.ImageKey = "folder_open";
node.SelectedImageKey = "folder_open";
}
// Check if the node has no children and if it is a folder
if (node.Nodes.Count == 1 && node.Nodes[0].Text == "Loading...")
{
node.Nodes.Clear();
MyLoadSubDirectoriesLazy(node, node.Tag.ToString());
}
}
// TREEVIEW - SET NODE IMAGE
private void TreeViewBackup_BeforeCollapse(object sender, TreeViewCancelEventArgs e)
{
// Retrieve click node select
TreeNode node = e.Node;
// Change image node - folder close
if (Directory.Exists(node.Tag?.ToString() ?? ""))
{
node.ImageKey = "folder";
node.SelectedImageKey = "folder";
}
}
|
:
Come puoi vedere ci sono alcune differenza rispetto il tuo approccio...
Esempio... per assegnare l'immagini, ho preferito usare l'accesso tramite "Chiave" e non per "Indice" come hai fatto tu.
Questo facilita e/o agevola la scrittura e la rilettura del codice.
Altro Esempio... utilizzo della Tag ; utile per il caricamento con il "metodo Lazy". Nella Tag viene salvata la Path di ogni Nodo e questo consente di caricare in modo "Lazy" via via i vari nodi nel momento in cui vengono espansi.
Il resto del codice utilizza semplicemente metodi molto classici e/o comuni.
E' tutto molto semplice e anche il codice è abbastanza commentato... se ti può tornare utile puoi prendere alcuni spunti.