Home > Back-end >  TreeView folder structure with a exception
TreeView folder structure with a exception

Time:09-23

I have two TreeViews and each of them generate a folder structure on a Drive. The program only has 1 comboBox to build both TreeViews in 2 drives. I only use one comboBox because almost every folder has the same name on F: and Z:

I say almost because I have 3 folders which have similair names but not the exact.

So let's say my DropDown looks like this:

Book1
Book2
Book3
Book4

So the dirs on Z: look like the example above, because that's the Source of my comboBox

And R: looks like this:

Book1
Book2
Book3_projects_render
Book4

So my Code works for Book1, Book2 and Book4 but when I click on Book3 on my DropDown and create my TreeView structure, it will create a new dir on R: named Book3 and the solution I want to achieve, is to make exceptions for dirs like Book3_projects_render so it won't make a new dir.

My Code:

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

    loremDropDown.DisplayMember = "Name";
    loremDropDown.ValueMember = "FullName";
    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();
    var shortcuts = new HashSet<string>();

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

        if (node.Level == 0) shortcuts.Add(sPath.TrimStart(driveF.ToArray()));
    }

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

        if (node.Level == 0) shortcuts.Add(sPath.TrimStart(driveZ.ToArray()));
    }

    foreach (var shortcut in shortcuts)
    {
        var dirF = $"{driveF}{shortcut}";
        var dirZ = $"{driveZ}{shortcut}";

        if (Directory.Exists(dirF) && Directory.Exists(dirZ))
        {
            CreateShortcut(dirF, dirZ);
            CreateShortcut(dirZ, dirF);
        }
    }
}

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

CodePudding user response:

Rename the TreeNode objects Before creating the Directories

Here's a way to rename given folders based on Jimi's suggestion.

  • Create a Dictionary<string, string> to have the target folders as keys and the new names as values.
  • For each TreeView control, clone its nodes in a temp TreeView to change the .Text properties of the target nodes without reflecting that on the main TreeView controls. Setting the .Text property is necessary to get the correct .FullPath property when you rename a parent and/or child node.
private void SomeButton_Click(object sender, EventArgs e)
{
    var driveF = "C:\\";
    var driveZ = "D:\\";
    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();
    var shortcuts = new HashSet<string>();
    var dirsToRename = new Dictionary<string, string>
    {
        { "Book 4", "Book 1" },
        { "Book 5", "Book 2" },
        { "Book 6", "Book 3" },
        { "Books", "Books 123" }
    };

    using (var tv = new TreeView())
    {
        tv.Nodes.AddRange(pathLorem.Nodes
            .OfType<TreeNode>()
            .Select(n => n.Clone() as TreeNode)
            .ToArray());

        foreach (var node in GetCheckedNodes(tv.Nodes))
        {
            if (dirsToRename.ContainsKey(node.Text)) node.Text = dirsToRename[node.Text];
            var sPath = Path.Combine(destPathF, node.FullPath.Replace(treeSep, dirSep));
            Directory.CreateDirectory(sPath);
            if (node.Level == 0) shortcuts.Add(sPath.TrimStart(driveF.ToArray()));
        }

        tv.Nodes.Clear();
        tv.Nodes.AddRange(ipsumPath.Nodes
            .OfType<TreeNode>()
            .Select(n => n.Clone() as TreeNode)
            .ToArray());

        foreach (var node in GetCheckedNodes(tv.Nodes))
        {
            if (dirsToRename.ContainsKey(node.Text)) node.Text = dirsToRename[node.Text];
            var sPath = Path.Combine(destPathZ, node.FullPath.Replace(treeSep, dirSep));
            Directory.CreateDirectory(sPath);
            if (node.Level == 0) shortcuts.Add(sPath.TrimStart(driveZ.ToArray()));
        }

        foreach (var shortcut in shortcuts)
        {
            var dirF = $"{driveF}{shortcut}";
            var dirZ = $"{driveZ}{shortcut}";

            if (Directory.Exists(dirF) && Directory.Exists(dirZ))
            {
                CreateShortcut(dirF, dirZ);
                CreateShortcut(dirZ, dirF);
            }
        }
    }
}

Rename given TreeNode objects based on destinations

The keys are taken from the ComboBox control.

private void btnTest_Click(object sender, EventArgs e)
{
    var driveF = "C:\\";
    var driveZ = "D:\\";
    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();
    var shortcuts = new HashSet<string>();
    var dirsToRename = new Dictionary<string, string>
    {
        { "Book 1", "Book 4" },
        { "Book 2", "Book 5" },
        { "Book 3", "Book 6" }
    };

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

        // Comment this if `pathLorem` is not the source of the keys...
        if (dirsToRename.ContainsKey(node.Text))
            sPath = Path.Combine(Path.GetDirectoryName(sPath), dirsToRename[node.Text]);

        Directory.CreateDirectory(sPath);

        if (node.Level == 0) shortcuts.Add(sPath.TrimStart(driveF.ToArray()));
    }

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

        // Comment this if `ipsumPath` is not the source of the keys...
        if (dirsToRename.ContainsKey(node.Text))
            sPath = Path.Combine(Path.GetDirectoryName(sPath), dirsToRename[node.Text]);

        Directory.CreateDirectory(sPath);

        if (node.Level == 0) shortcuts.Add(sPath.TrimStart(driveZ.ToArray()));
    }

    foreach (var shortcut in shortcuts)
    {
        var dirF = $"{driveF}{shortcut}";
        var dirZ = $"{driveZ}{shortcut}";

        if (Directory.Exists(dirF) && Directory.Exists(dirZ))
        {
            CreateShortcut(dirF, dirZ);
            CreateShortcut(dirZ, dirF);
        }
    }
}

You can add a control such as DataGridView to get the key-value pairs of the dirsToRename dictionary instead of the hard-code.

Rename a Directory after creating it

You can rename a system file or directory by calling the .Move method of the File and Directory classes respectively.

// Rename a file...
File.Move("source", "destination");

// Rename a directory...
Directory.Move("source", "destination");

Map a selected Directory to another

To map a selected directory from the ComboBox to another directory, change destPathF or destPathZ (not both) depending on the location of the target (Book3_projects_render for example) directory.

For example:

private void SomeButton_Click(object sender, EventArgs e)
{
    var driveF = "C:\\";
    var driveZ = "D:\\";
    var selDirInfo = loremDropDown.SelectedItem as DirectoryInfo;
    var selDir = selDirInfo.FullName;
    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();
    var shortcuts = new HashSet<string>();

    if (selDirInfo.Name == "Book 3")
    {
        // If `Book3_projects_render` is on F: otherwise comment...
        //destPathF = Path.Combine(Path.GetDirectoryName(destPathF), "Book3_projects_render");

        // If `Book3_projects_render` is on Z: otherwise comment...
        destPathZ = Path.Combine(Path.GetDirectoryName(destPathZ), "Book3_projects_render");
    }

    foreach (var node in GetCheckedNodes(pathLorem.Nodes))
    {
        var sPath = Path.Combine(destPathF, node.FullPath.Replace(treeSep, dirSep));
        Directory.CreateDirectory(sPath);
        if (node.Level == 0) shortcuts.Add(sPath.TrimStart(driveF.ToArray()));
    }

    foreach (var node in GetCheckedNodes(ipsumPath.Nodes))
    {
        var sPath = Path.Combine(destPathZ, node.FullPath.Replace(treeSep, dirSep));
        Directory.CreateDirectory(sPath);
        if (node.Level == 0) shortcuts.Add(sPath.TrimStart(driveZ.ToArray()));
    }

    foreach (var shortcut in shortcuts)
    {
        var dirF = $"{driveF}{shortcut}";
        var dirZ = $"{driveZ}{shortcut}";

        if (Directory.Exists(dirF) && Directory.Exists(dirZ))
        {
            CreateShortcut(dirF, dirZ);
            CreateShortcut(dirZ, dirF);
        }
    }
}
  • Related