我有一个WinForm应用程序,它采用两个TreeView的 struct ,并将它们作为文件夹实现到用户在下拉菜单中 Select 的路径中.

下拉菜单当前获取Z:中的所有可选文件夹

现在,我的TreeView loremPath具有正确的驱动器Z:,但ipsumPath应该放入R: 但使用相同的Drop Down-因为第二个Drive的文件夹 struct 是exact作为Z:所以我不需要构建一个全新的Drop Down,我只需要将ipsumPath中的路径更改为R:,并且可以为两个Treeview使用一个Drop Down.

所以我之前在StackOverflow上有一个问题,有人建议我对两个Treeview都使用硬编码路径,但我不知道如何实现.

I tried something like:

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

但这并没有起到任何作用.

My whole 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<TreeNode>().Any(n => n.Checked);
        }

        private IEnumerable<TreeNode> GetCheckedNodes(TreeNodeCollection nodeCol)
        {
            foreach (TreeNode node in nodeCol)
            {
                if (node.Checked ||
                    node.Nodes.Cast<TreeNode>().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<TreeNode>().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<TreeNode> 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<TreeNode> Parents(this TreeNode node)
        {
            var p = node.Parent;

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

                p = p.Parent;
            }
        }
    }
}

推荐答案

您在这里试图解决的问题是在文件系统中镜像选中的TreeNode个分支,并在目标目录中创建类似的目录 struct .目标目录可以位于特定驱动器之一中,例如R:Z:.所以,让我们把它分解一下.

Destination Drives

首先,您需要在列表控件(如ComboBox)中列出目标驱动器以 Select 一个.您可以通过DriveInfo.GetDrives的方法获取系统中已修复和就绪的驱动器,如果不想全部列出,也可以手动添加它们.我将在这里使用后一种方法.从这里,在设计器中,放置一个ComboBox并将其命名为cmbDrives,然后添加窗体的构造函数:

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

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

Destination Directories

您已经 Select 了loremDropDown组合框,其中列出了目标目录/文件夹.处理cmbDrives.SelectedIndexChanged事件以填充选定驱动器中的目标目录.重新访问构造函数以添加:

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

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

    loremDropDown.DisplayMember = "Name";
    loremDropDown.ValueMember = "FullName"; 
}

并添加事件处理程序:

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

现在,例如,当您 Select R:驱动器时,loremDropDown.SelectedValue将返回所选目标目录的完整路径,如R:\\SomeSelectedDirectory\.当您 Select 另一个驱动器(如Z:)时,同一目录的路径将为Z:\\SomeSelectedDirectory\.所以你不需要做其他任何事情.

Create the Directory Structure

从上一个答案中得出:

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

    // The same for `ipsumPath` TreeView if the target destination is the same.
}

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

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

SO73649197


另一方面,如果您有两个TreeView控件,并且需要同时在两个不同的驱动器中创建目录 struct ,其中两个驱动器具有相同的目标目录 struct ,那么您只需更改驱动器...(忽略此场景中的cmbDrives)...

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

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

private void SomeButton_Click(object sender, EventArgs e)
{
    var drive = "F:\\";
    var selDir = loremDropDown.SelectedValue.ToString();
    var destPath = selDir.Replace(Path.GetPathRoot(selDir), drive);
    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);
    }

    CreateShortcutToCurrentAssembly(destPath);

    drive = "Z:\\";
    destPath = selDir.Replace(Path.GetPathRoot(selDir), drive);

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

    CreateShortcutToCurrentAssembly(destPath);
}

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

此外,如果pathLoremipsumPath都可以在F:Z:或其他地方输出,那么您需要结合这里提到的两个 idea ,并添加两个驱动器 Select 器(例如,ComboBox)从它们中 Select 每个的目的地驱动器,而不是对它们进行硬编码.或者,如果一次处理一个TreeView是可以接受的,那么您只需要一个cmbDrives组合框和两个RadioButton控件来相应地 Select 要处理的pathLoremipsumPath个控件.

Csharp相关问答推荐

如何使用FastEndpoints和.NET 8 WebAppliationBuilder进行集成测试?

如何保持主摄像头视角保持一致?

处理. netstandard2.0项目中HttpClient.SslProtocol的PlatformNotSupportedException问题""

始终保留数组中的最后N个值,丢弃最老的

只有第一个LINQ.Count()语句有效

最新的Mediatr和具有同步方法的处理程序Handle:并非所有代码路径都返回值"

Rider将.NET安装在哪里

应用程序重新启动后,EFCore列表的BSON反序列化错误

异步实体框架核心查询引发InvalidOperation异常

取决于您的数据量的多个嵌套循环

带有可选参数的模拟方法返回意外的不同值,具体取决于可选的默认值

在DoubleClick上交换DataGridViewImageColumn的图像和工具提示

如何将FindAll()与Nuget包Interop.UIAutomationClient一起使用

GODOT 4向C#中的字符串参数发送信号以等待

用于获取字符串的最后12个字符的正则表达式(空格除外)

C#静态抽象属性不能被子接口覆盖

C#中COM对象的实际地址

无效的Zip文件-Zip存档

如何使用LINQ在C#中填充列表列表?

最小API定义的Swagger标头参数