3 votes

Deux structures d'arborescence dans deux lecteursTreeView

J'ai une application WinForm qui prend la structure de deux TreeViews et les implémente en tant que dossiers dans le chemin que les utilisateurs ont choisi dans le menu déroulant.

Le menu déroulant obtient actuellement tous les dossiers sélectionnables depuis Z:

Maintenant, mon TreeView loremPath a le bon lecteur avec Z: mais ipsumPath devrait aller dans R: mais avec le même menu déroulant - Parce que le deuxième lecteur a la structure de dossiers exacte que Z: donc au lieu de construire un tout nouveau menu déroulant, je dois juste changer le chemin dans ipsumPath en R: et je peux utiliser un seul menu déroulant pour les deux Treeviews.

Alors j'avais une question précédente sur StackOverflow et on m'a recommandé d'utiliser des chemins codés en dur pour les deux TreeViews, mais je n'arrive pas à comprendre comment implémenter cela.

J'ai essayé quelque chose comme:

        var testPath = new DirectoryInfo("R:\\").GetDirectories();
        var treeSeperator = ipsumPath.PathSeparator;
        var dirSep = Path.DirectorySeparatorChar.ToString();

        foreach (var node in GetCheckedNodes(ipsumPath.Nodes))
        {
            var sPath = Path.Combine(testPath.ToString(), node.FullPath.Replace(treeSeperator, dirSep));
            Directory.CreateDirectory(sPath);
        }

Mais cela n'a pas du tout fonctionné.

Tout mon code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
using IWshRuntimeLibrary;
using System.Reflection;

namespace Form1
{
    public partial class Form1 : Form
    {
        [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
        private static extern IntPtr CreateRoundRectRgn
         (
             int nLeftRect,
             int nTopRect,
             int nRightRect,
             int nBottomRect,
             int nWidthEllipse,
             int nHeightEllipse
         );

        public Form1()
        {
            InitializeComponent();
            this.FormBorderStyle = FormBorderStyle.None;
            Region = System.Drawing.Region.FromHrgn(CreateRoundRectRgn(0, 0, Width, Height, 20, 20));
            foreach (TreeNode tn in loremPath.Nodes)
            {
                tn.Expand();
            }
            foreach (TreeNode tn in ipsumPath.Nodes)
            {
                tn.Expand();
            }
            ipsumDropDown.Items.AddRange(new[] { "R:\\", "Z:\\" });
            loremDropDown.DataSource = new DirectoryInfo($"{ipsumDropDown.SelectedItem}").GetDirectories();
        }

        private void CreateShortcutToCurrentAssembly(string saveDir)
        {
            var testPath = loremDropDown.SelectedValue.ToString();
            WshShell wshShell = new WshShell();
            string fileName = testPath + "\\" + Application.ProductName + ".lnk";
            IWshShortcut shortcut = (IWshShortcut)wshShell.CreateShortcut(fileName);
            shortcut.TargetPath = Application.ExecutablePath;
            shortcut.Save();
        }

        private void close_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.Application.Exit();
        }

        private void loremPath_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (e.Action == TreeViewAction.Unknown) return;

            foreach (TreeNode n in e.Node.Children())
                n.Checked = e.Node.Checked;

            foreach (TreeNode p in e.Node.Parents())
                p.Checked = p.Nodes.OfType().Any(n => n.Checked);
        }

        private IEnumerable GetCheckedNodes(TreeNodeCollection nodeCol)
        {
            foreach (TreeNode node in nodeCol)
            {
                if (node.Checked ||
                    node.Nodes.Cast().Any(n => n.Checked))
                {
                    yield return node;
                }

                foreach (TreeNode childNode in GetCheckedNodes(node.Nodes))
                {
                    if (childNode.Checked)
                        yield return childNode;
                }
            }
        }
        private void projektordnerGenerieren_Click(object sender, EventArgs e)
        {
            var destPath = loremDropDown.SelectedValue.ToString();
            var treeSep = loremPath.PathSeparator;
            var dirSep = Path.DirectorySeparatorChar.ToString();

            foreach (var node in GetCheckedNodes(loremPath.Nodes))
            {
                var sPath = Path.Combine(destPath, node.FullPath.Replace(treeSep, dirSep));
                Directory.CreateDirectory(sPath);
            }
            foreach (var node in GetCheckedNodes(ipsumPath.Nodes))
            {
                var sPath = Path.Combine(destPath, node.FullPath.Replace(treeSep, dirSep));
                Directory.CreateDirectory(sPath);
            }
            string folder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            CreateShortcutToCurrentAssembly(folder);
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            this.loremPath.SelectedNode = this.loremPath.Nodes[0];
            this.ipsumPath.SelectedNode = this.ipsumPath.Nodes[0];
            loremPath.SelectedNode.Text = textBox1.Text;
            ipsumPath.SelectedNode.Text = textBox1.Text;
        }

        private void ipsumPath_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (e.Action == TreeViewAction.Unknown) return;

            foreach (TreeNode n in e.Node.Children())
                n.Checked = e.Node.Checked;

            foreach (TreeNode p in e.Node.Parents())
                p.Checked = p.Nodes.OfType().Any(n => n.Checked);
        }

        public const int WM_NCLBUTTONDOWN = 0xA1;
        public const int HT_CAPTION = 0x2;

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern bool ReleaseCapture();

        private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                ReleaseCapture();
                SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
            }
        }

        private void alleErweitern_Click(object sender, EventArgs e)
        {
            foreach (TreeNode tn in loremPath.Nodes)
            {
                tn.Expand();
            }
            foreach (TreeNode tn in ipsumPath.Nodes)
            {
                tn.Expand();
            }
        }

        private void alleReduzieren_Click(object sender, EventArgs e)
        {
            foreach (TreeNode tn in loremPath.Nodes)
            {
                tn.Collapse();
            }
            foreach (TreeNode tn in ipsumPath.Nodes)
            {
                tn.Collapse();
            }
        }

        private void minimize_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
        }
    }
    static class TreeViewExtensions
    {
        public static IEnumerable Children(this TreeNode node)
        {
            foreach (TreeNode n in node.Nodes)
            {
                yield return n;

                foreach (TreeNode child in Children(n))
                    yield return child;
            }
        }

        public static IEnumerable Parents(this TreeNode node)
        {
            var p = node.Parent;

            while (p != null)
            {
                yield return p;

                p = p.Parent;
            }
        }
    }
}

3voto

dr.null Points 1217

Le problème que vous essayez de résoudre ici est de refléter les branches TreeNode sélectionnées dans le système de fichiers et de créer une structure de répertoire similaire dans un répertoire de destination. Un répertoire de destination peut être situé sur l'un des lecteurs spécifiques tels que R: et Z:. Alors, décomposons cela.

Lecteurs de destination

Tout d'abord, vous devez répertorier les lecteurs cibles dans un contrôle de liste tel que ComboBox pour en sélectionner un. Vous pouvez obtenir les lecteurs fixes et prêts de votre système en utilisant la méthode DriveInfo.GetDrives ou les ajouter manuellement si vous ne voulez pas tous les répertorier. J'utiliserai ici l'approche de la seconde option. À partir de là, dans le concepteur, ajoutez un ComboBox et nommez-le cmbDrives, puis ajoutez dans le constructeur du formulaire :

public Form1()
{
    InitializeComponent();
    // ...

    cmbDrives.Items.AddRange(new[] { "R:\\", "Z:\\" });
    cmbDrives.SelectedIndex = 0;  
}

Répertoires de destination

Vous avez déjà le loremDropDown menu déroulant qui répertorie les répertoires/dossiers de destination. Gérez l'événement cmbDrives.SelectedIndexChanged pour peupler les répertoires de destination dans le lecteur sélectionné. Revenez sur le constructeur pour ajouter :

public Form1()
{
    InitializeComponent();
    // ...

    cmbDrives.Items.AddRange(new[] { "R:\\", "Z:\\" });
    cmbDrives.SelectedIndex = 0; 

    loremDropDown.DisplayMember = "Nom";
    loremDropDown.ValueMember = "NomComplet"; 
}

Et ajoutez le gestionnaire d'événements :

private void cmbDrives_SelectedIndexChanged(object sender, EventArgs e)
{
    var selDrive = cmbDrives.SelectedItem.ToString();
    loremDropDown.DataSource = new DirectoryInfo(selDrive).GetDirectories();
}

Maintenant, lorsque vous sélectionnez le lecteur R: par exemple, loremDropDown.SelectedValue retourne le chemin complet du répertoire de destination sélectionné comme R:\\UnRépertoireSélectionné\. Lorsque vous sélectionnez un autre lecteur comme Z:, le chemin du même répertoire sera Z:\\UnRépertoireSélectionné\. Vous n'avez donc rien d'autre à faire.

Créer la structure de répertoire

Repris de la réponse précédente :

private void SomeButton_Click(object sender, EventArgs e)
{
    var destPath = loremDropDown.SelectedValue.ToString();
    var treeSep = pathLorem.PathSeparator;
    var dirSep = Path.DirectorySeparatorChar.ToString();

    foreach (var node in GetCheckedNodes(pathLorem.Nodes))
    {
        var sPath = Path.Combine(destPath, node.FullPath.Replace(treeSep, dirSep));
        Directory.CreateDirectory(sPath);
    }

    // La même chose pour `ipsumPath` TreeView si la destination cible est la même.
}

private IEnumerable GetCheckedNodes(TreeNodeCollection nodeCol)
{
    foreach (TreeNode node in nodeCol)
    {
        if (node.Checked ||
            node.Nodes.Cast().Any(n => n.Checked))
        {
            yield return node;
        }

        foreach (TreeNode childNode in GetCheckedNodes(node.Nodes))
        {
            if (childNode.Checked)
                yield return childNode;
        }
    }
}

SO73649197


D'autre part, si vous avez deux contrôles TreeView et que vous devez créer des structures de répertoires dans deux lecteurs différents en même temps où les deux lecteurs ont la même structure de répertoire de destination, alors il vous suffit de changer le lecteur... (ignorez le cmbDrives dans ce scénario)...

public Form1()
{
    InitializeComponent();
    // ...

    loremDropDown.DisplayMember = "Nom";
    loremDropDown.ValueMember = "NomComplet";
    loremDropDown.DataSource = new DirectoryInfo("F:\\").GetDirectories();
}

private void SomeButton_Click(object sender, EventArgs e)
{
    var driveF = "F:\\";
    var driveZ = "Z:\\";
    var selDir = loremDropDown.SelectedValue.ToString();
    var destPathF = selDir.Replace(Path.GetPathRoot(selDir), driveF);
    var destPathZ = selDir.Replace(Path.GetPathRoot(selDir), driveZ);
    var treeSep = pathLorem.PathSeparator;
    var dirSep = Path.DirectorySeparatorChar.ToString();

    foreach (var node in GetCheckedNodes(pathLorem.Nodes))
    {
        var sPath = Path.Combine(destPathF, node.FullPath.Replace(treeSep, dirSep));
        Directory.CreateDirectory(sPath);
    }

    foreach (var node in GetCheckedNodes(ipsumPath.Nodes))
    {
        var sPath = Path.Combine(destPathZ, node.FullPath.Replace(treeSep, dirSep));
        Directory.CreateDirectory(sPath);
    }

    CreateShortcut(destPathF, destPathZ);
    CreateShortcut(destPathZ, destPathF);
}

private void CreateShortcut(string shortcutPath, string targetPath)
{
    WshShell wshShell = new WshShell();
    string fileName = Path.Combine(shortcutPath, $"{Application.ProductName}.lnk");
    IWshShortcut shortcut = (IWshShortcut)wshShell.CreateShortcut(fileName);
    shortcut.TargetPath = targetPath;
    shortcut.Save();
}

De plus, s'il est possible que pathLorem et ipsumPath chacun d'entre eux puissent être générés dans F: ou Z: ou ailleurs, alors vous devez combiner les deux idées mentionnées ici et ajouter deux sélecteurs de lecteur (par exemple ComboBox) pour sélectionner à partir d'eux le lecteur de destination pour chacun au lieu de les coder en dur. Ou, si le fait de traiter un TreeView à la fois est acceptable, alors vous avez simplement besoin d'un seul ComboBox et de deux contrôles RadioButton pour sélectionner en conséquence le contrôle pathLorem ou ipsumPath à traiter.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X