C# 基于纯文本在TreeView中显示TFS测试用例';文件夹';财产

C# 基于纯文本在TreeView中显示TFS测试用例';文件夹';财产,c#,tfs,treeview,C#,Tfs,Treeview,我们部门使用的测试用例从SpiraTeam迁移到TFS中。SpiraTeam允许将测试用例存储在文件夹层次结构中,例如 订购/订购和库存/发送订单/测试1:发送正常订单 TFS不支持此层次结构,因此,在迁移过程中,我们将每个测试的文件夹层次结构复制为纯文本,现在将其存储在名为“文件夹”的TFS工作项中的纯文本字段中 我正在开发一个小型C#应用程序,它允许在这个层次结构中查看和编辑测试用例 我计划从层次结构构建一个树视图来显示测试用例 我拥有检索测试用例的所有功能,目前将它们存储在应用程序内的Wo

我们部门使用的测试用例从SpiraTeam迁移到TFS中。SpiraTeam允许将测试用例存储在文件夹层次结构中,例如

订购/订购和库存/发送订单/测试1:发送正常订单

TFS不支持此层次结构,因此,在迁移过程中,我们将每个测试的文件夹层次结构复制为纯文本,现在将其存储在名为“文件夹”的TFS工作项中的纯文本字段中

我正在开发一个小型C#应用程序,它允许在这个层次结构中查看和编辑测试用例

我计划从层次结构构建一个树视图来显示测试用例

我拥有检索测试用例的所有功能,目前将它们存储在应用程序内的WorkItemStore中,但我有两个问题:

  • 如何在树状视图中显示此信息?我知道我将不得不使用递归算法,但是关于这个主题的任何研究都会带来关于如何从实际的Windows目录构建TreeView的说明,而不是我需要使用的纯文本字段。首先,我使用.Split方法将“Folder”字段拆分为字符串数组

  • 一旦我将信息输入到TreeView中,我将如何根据TreeView中的选择导航到WorkItemStore中的正确测试用例,因为TreeView节点似乎基于字符串?以上面的路径为例,我想要一个比从[Title]=“test1:sendanormalorder”的存储中选择工作项更优雅的解决方案

  • 也许我的第二个问题的解决方案将决定我如何实现这一点,而我的第一个问题可能与此无关

    在此方面的一些建议将不胜感激

    谢谢


    Andy

    下面是一个可以在LinqPad中运行的示例程序。它接受一个WorkItem(在本例中是我创建的一个类),并在通过
    /
    拆分它之后沿着路径遍历,在前进的过程中沿行创建节点,如果它在同一集合中找到具有相同文本的节点,它将改为使用该节点

    void Main()
    {
        //Create a treeview with a root node.
        TreeView tv = new TreeView();
        tv.ShowNodeToolTips = true; //Turn on tooltips for this demo.
        tv.Nodes.Add(new TreeNode("Root"));
    
        //These may need ordering by path before you start.
        var tfsTestCases = new[]
        {
            new WorkItem { Path = "Module/Feature1/SubFeature1/Test1", WorkItemId = 1, },
            new WorkItem { Path = "Module/Feature1/SubFeature1/Test2", WorkItemId = 2, },
            new WorkItem { Path = "Module/Feature1/SubFeature2/Test1", WorkItemId = 3, },
            new WorkItem { Path = "Module/Feature1/SubFeature2/Test2", WorkItemId = 4, },
            new WorkItem { Path = "Module/Feature2/SubFeature1/Test1", WorkItemId = 5, },
            new WorkItem { Path = "Module/Feature2/SubFeature1/Test2", WorkItemId = 6, },
        };
    
        //Looping through the test cases...
        foreach (var testCase in tfsTestCases)
        {
            //Start at the root of the tree for each work item.
            TreeNode lastNode = tv.Nodes[0];
    
            //Loop through each part of the path and create a new node.
            //Use the NodeCollection from the one we just created each time through the loop.
            //This allows the next iteration to "walk down" as it goes.
            foreach (var part in testCase.Path.Split('/'))
                lastNode = AddTreeNode(lastNode.Nodes, part);
    
            //Set the Tag on the last node in the loop, this is the one with the actual Test Case.
            //You can reference the Tag property of "tv.SelectedNode" to get access to the Work Item. If the Tag is null, then it's not a Test Case.
            lastNode.Tag = testCase;
            lastNode.ToolTipText = testCase.WorkItemId.ToString();  //Set for this DEMO.
        }
        //Display the tree.
        tv.Dump();
    }
    
    TreeNode AddTreeNode(TreeNodeCollection nodes, String path)
    {
        //Try and find a node in the collection matching the specified pathPath.
        var node = nodes.Cast<TreeNode>().Where(node => node.Text == path).SingleOrDefault();
        //If it's not found, create it and add it to the collection of nodes we just searched.
        if (node == null)
        {
            node = new TreeNode(path);
            nodes.Add(parentNode);
        }
        //We need this later, so pass it back.
        return node;
    }
    
    class WorkItem
    {
        public String Path { get; set; }
        public Int32 WorkItemId { get; set; }
        //etc.
    }
    
    void Main()
    {
    //创建具有根节点的树视图。
    TreeView tv=新的TreeView();
    tv.ShowNodeToolTips=true;//打开此演示的工具提示。
    添加(新树节点(“根”);
    //在开始之前,可能需要按路径进行排序。
    var tfsTestCases=new[]
    {
    新工作项{Path=“Module/Feature1/SubFeature1/Test1”,工作项ID=1,},
    新工作项{Path=“Module/Feature1/SubFeature1/Test2”,工作项ID=2,},
    新工作项{Path=“Module/Feature1/SubFeature2/Test1”,工作项ID=3,},
    新工作项{Path=“Module/Feature1/SubFeature2/Test2”,工作项ID=4,},
    新工作项{Path=“Module/Feature2/SubFeature1/Test1”,工作项ID=5,},
    新工作项{Path=“Module/Feature2/SubFeature1/Test2”,工作项ID=6,},
    };
    //在测试用例中循环。。。
    foreach(tfsTestCases中的var testCase)
    {
    //从每个工作项的树的根开始。
    TreeNode lastNode=tv.Nodes[0];
    //循环遍历路径的每个部分并创建一个新节点。
    //在循环中使用我们每次刚创建的节点集合。
    //这允许下一次迭代在进行时“向下走”。
    foreach(testCase.Path.Split('/')中的变量部分)
    lastNode=AddTreeNode(lastNode.Nodes,零件);
    //在循环中的最后一个节点上设置标记,这是一个具有实际测试用例的节点。
    //您可以引用“tv.SelectedNode”的标记属性来访问工作项。如果标记为null,则它不是测试用例。
    Tag=testCase;
    lastNode.ToolTipText=testCase.WorkItemId.ToString();//为此演示设置。
    }
    //显示树。
    tv.Dump();
    }
    TreeNode AddTreeNode(TreeNodeCollection节点,字符串路径)
    {
    //尝试在集合中查找与指定路径匹配的节点。
    var node=nodes.Cast().Where(node=>node.Text==path.SingleOrDefault();
    //如果找不到,创建它并将其添加到我们刚才搜索的节点集合中。
    if(node==null)
    {
    节点=新树节点(路径);
    添加(父节点);
    }
    //我们以后需要这个,所以把它传回去。
    返回节点;
    }
    类工作项
    {
    公共字符串路径{get;set;}
    公共Int32工作项ID{get;set;}
    //等等。
    }