【问题标题】:Tree view control, get next available node name from the max value树视图控件,从最大值获取下一个可用节点名
【发布时间】:2021-11-30 14:29:35
【问题描述】:

如果存在具有指定名称的节点,我正在研究一种方法,该方法会给出下一个可用节点名称。但想法是该方法从最大值给出下一个,例如:

如果我添加一个名为“test”的新节点,该方法应该返回“test6”而不是“test2”。包含数字作为名称的节点也会发生同样的情况:

如果我添加一个名为“20”的新节点,下一个可用的名称应该是“31”。

所以我们的想法是从序列中获取“最大值”并将其添加到其中。这个树节点很容易包含超过500个节点,所以这个方法的优化非常重要。我一直在尝试使用此代码执行此操作,但没有按预期工作:

internal static string GetNextAvailableName(TreeView treeView, string searchFor)
{
    //Check if item exists
    if (NodeExistsInSection(treeView, searchFor))
    {
        return searchFor;
    }
    else
    {
        //Initialize variables
        string nextAvailableName = searchFor;
        int counter = 0;

        Match result = Regex.Match(searchFor, @"\d+$", RegexOptions.RightToLeft);
        if (result.Success)
        {
            counter = int.Parse(result.Value);
            if (searchFor.Length >= result.Value.Length)
            {
                searchFor = searchFor.Substring(0, (searchFor.Length - result.Value.Length));
            }
        }


        while (SearchRecByText(treeView, nextAvailableName) != null)
        {
            counter++;
            nextAvailableName = string.Join("", searchFor, counter);
        }

        return nextAvailableName;
    }
}

internal static bool NodeExistsInSection(TreeView treeView, string searchFor)
{
    bool nodeExists = false;

    // Print each node recursively.  
    foreach (TreeNode n in treeView.Nodes)
    {
        //recursiveTotalNodes++;
        if (LoopNodesRecursive(n, searchFor) != null)
        {
            nodeExists = true;
            break;
        }
    }

    return nodeExists;
}

internal static TreeNode SearchRecByText(TreeView treeView, string searchFor)
{
    TreeNode matchedNode = null;

    // Print each node recursively.  
    foreach (TreeNode n in treeView.Nodes)
    {
        //recursiveTotalNodes++;
        matchedNode = LoopNodesRecursive(n, searchFor);
        if (matchedNode != null)
        {
            break;
        }
    }

    return matchedNode;
}

private static TreeNode LoopNodesRecursive(TreeNode treeNode, string searchFor)
{
    // Visit each node recursively.  
    foreach (TreeNode tn in treeNode.Nodes)
    {
        if (tn.Text.Equals(searchFor, StringComparison.OrdinalIgnoreCase))
        {
            return tn;
        }
    }
    return null;
}

【问题讨论】:

  • 树是否允许在不同的分支中包含重复的lead节点?
  • “它没有按预期工作”不是一个好的大报告。在每个好的错误报告都应该包含的期望-实际-差异三角形中,你只做了一个;至少需要两个。说明您的实际情况和/或您的差异

标签: c# winforms treeview treenode


【解决方案1】:

如果性能是您的直接目标,我想我会有一个字典跟踪树节点,如果用户输入一个数字,则有一个特殊情况。从发布的代码看来,节点必须在整个树中唯一命名。因此,我会在树初始化的基础上构建一个字典并随时维护它

这是根据用户键入的内容建议新节点名称的方法:

Dictionary<string, int> prefixes = new();

string GetNodeName(string prefix){

    //strip trailing numbers entered by the user
    prefix = Regex.Replace(prefix, "\\d+$", "");

    //have we seen the prefix before?
    var n = prefixes.GetValueOrDefault(prefix, 0);

    prefixes[prefix] = n + 1;

    if(n > 0) //nth time we saw it, return number suffix 
      return prefix+n;
    if(prefix == "") //user entered just a number, for the first time
      return "1";
    return prefix; //user entered a new prefix 
    
}

GetNodeName 通过去除尾随数字并检查生成的前缀的下一个已知数字是什么来识别用户键入的前缀文本。如果前缀未知,则为 0,然后添加 1 作为下一个数字,并且 0 特殊情况下“没有数字后缀”


如果我们需要从某个地方恢复树,我们需要构建我们在构建时看到的 max+1 值:

 void Build(string nodename){

    //strip trailing numbers
    var prefix = Regex.Replace(prefix, "\\d+$", "");

    //get the number off the end. Uses c# 8 ranges; if your c# version is less, use Remove(length) instead
    var number = int.Parse(nodename[prefix.Length..]);

    //have we seen the prefix before?
    var n = prefixes.GetValueOrDefault(prefix, 0);

    //node number is higher than dictionary? Bump dict 
    if(number >= n)
      prefixes[prefix] = number + 1;
}

从 DB 或其他东西重建树时,为每个节点文本调用 build;它会将前缀字典中的数字增加为它所看到的任何内容的 +1


我认为允许用户重复输入“test2”前缀是一个逻辑错误,您将创建“test2”、“test21”、test22”的节点 - 我认为前缀是“test”,用户提供的 2 被忽略,节点获取“test”的下一行,即“test7”。如果用户只输入一个数字,则此逻辑有效,前缀为“”并相应编号

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2021-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多