【问题标题】:How to reset Treeview to default display after Treeview.Sort?如何在 Treeview.Sort 之后将 Treeview 重置为默认显示?
【发布时间】:2015-04-20 04:22:48
【问题描述】:

我试图按字母顺序显示树视图的节点并设法通过以下方式完成它:

treeview1.Sort();  

它负责排序。但后来我希望可以选择将树视图恢复到其原始显示状态(没有字母排序)。

on another question 我看到我可以使用树视图的属性:.sorted 并将其设置为 true 或 false,但它对我没有任何作用。

我在控件中有数据,它已经在设计时设置了。

最好的方法是什么?

提前非常感谢!

【问题讨论】:

  • 您正在寻找幻像 Unsort() 方法。在您对树进行排序之前,它使用了 200 多兆字节的树外观副本。当然不存在,把数据从视图中分离出来,就变得简单了。
  • @HansPassant 感谢您的回答,所以您的意思是,最好的方法可能是将数据序列化为 XML 文档,然后在清除所有排序节点后将其反序列化回树视图?
  • 没有。他的意思是他所说的。在您解释数据的来源以及它们如何进入树之前,我们无法为您提供更具体的建议..
  • @TaW 我认为这很明显,Hans 也得到了我,数据在控制中,它已经在设计时设置。所以他提出要分开,我想确定是这样的
  • 不像你想象的那么明显。但既然就是这样,您可以简单地将其放入 LoadTree() 例程中,而不是您可以随时使用的设计器中。它不像 XML 文件那样灵活,而是自包含的。

标签: c# winforms sorting treeview


【解决方案1】:

当然,从外部来源获取内容是填写Tree 最灵活的方式,但是..

..由于树的内容已添加到设计器中,因此如果涉及大量数据,最佳途径可能是将设计器代码移动到神奇的Unsort-函数中来挽救这些数据,您可以随时打电话。

仔细查看表单的Designer.cs 文件!在这里您可以找到两个处理TreeView 加载的部分:

  • 第一个坐在“禁止”部分内:InitializeComponent()带有可怕的警告,您不应该更改其中的任何内容。好吧,别担心,我们所做的只是将其中的几行复制到 unsort 函数中。

我们需要的是所有声明和创建节点的行。它们看起来像这样:

System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("John");

现在向下滚动到开头的部分

   // 
   // treeView1
   // 

我们不关心将NameLocation 分配给TreeView 的前几行。但是我们想要 all 以下几行来设置 allNamesTexts Nodes;以及将根节点添加到 TreeView..

的所有行

我们将所有这些复制到一个函数中,该函数首先清除 Nodes 并重置 Sorted 属性。然后是我们从设计师那里抢救出来的所有线条。

结果可能如下所示:

void unsortTree()
{
   this.treeView1.Nodes.Clear();
   this.treeView1.Sorted = false;
    
   System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("John");
   System.Windows.Forms.TreeNode treeNode2 = new System.Windows.Forms.TreeNode("Paul");
   System.Windows.Forms.TreeNode treeNode3 = new System.Windows.Forms.TreeNode("George");
   System.Windows.Forms.TreeNode treeNode4 = new System.Windows.Forms.TreeNode("Ringo");
   System.Windows.Forms.TreeNode treeNode5 = new System.Windows.Forms.TreeNode("Beatles",
                 new System.Windows.Forms.TreeNode[] 
                 {treeNode1,  treeNode2, treeNode3, treeNode4});
   System.Windows.Forms.TreeNode treeNode6 = new System.Windows.Forms.TreeNode("Byrds");
   System.Windows.Forms.TreeNode treeNode7 = 
         new System.Windows.Forms.TreeNode("Bee Gees");

   // 
   // treeView1
   // 

   treeNode1.Name = "Knoten2";        treeNode1.Text = "John";
   treeNode2.Name = "Knoten3";        treeNode2.Text = "Paul";
   treeNode3.Name = "Knoten4";        treeNode3.Text = "George";
   treeNode4.Name = "Knoten6";        treeNode4.Text = "Ringo";
   treeNode5.Name = "Knoten0";        treeNode5.Text = "Beatles";
   treeNode6.Name = "Knoten1";        treeNode6.Text = "Byrds";
   treeNode7.Name = "Knoten7";        treeNode7.Text = "Bee Gees";

   this.treeView1.Nodes.AddRange(new System.Windows.Forms.TreeNode[]
                                { treeNode5,   treeNode6, treeNode7});

}

我们您已经测试过,这可以正常工作,您可以从设计器中的树中删除节点,并将对该函数的调用添加到表单加载中。不要将数据保存在两个地方!!

注意:由于这会从头开始重新创建树内容,所有用户输入都会丢失。如果用户可以检查CheckBoxes 或编辑Labels,您应该考虑编写treesave 和treeload 函数! (不一定针对文件,可能只是一个不可见的辅助树视图..)

注2:

由于TreeView 确实包含CheckBoxes(但既不添加也不删除Nodes 也不更改Texts)我们应该存储和恢复CheckStates

在类级别添加Dictionary 和这两个递归辅助函数几乎是我们所需要的:

Dictionary<string, bool> tvCheckStates = null;

void storeChecks(TreeNode node)
{
    if (tvCheckStates.Keys.Contains(node.Name))
        throw new Exception("duplicate node name:" + node.Name);
    else tvCheckStates.Add(node.Name, node.Checked);

    foreach (TreeNode n in node.Nodes) storeChecks(n);
}

void restoreChecks(TreeNode node)
{
    if (tvCheckStates.Keys.Contains(node.Name))
        node.Checked = tvCheckStates[node.Name];
    else throw new Exception("node not found:" + node.Name);

    foreach (TreeNode n in node.Nodes) restoreChecks(n);
}

最后我们在'unsort'的开头和结尾调用它们:

  {
      if (tvCheckStates == null && treeView1.Nodes.Count > 0) 
          tvCheckStates = new Dictionary<string, bool>();
      else if (treeView1.Nodes.Count > 0) tvCheckStates.Clear();
      foreach (TreeNode node in treeView1.Nodes) storeChecks(node);
      //..

      //..
      if (tvCheckStates != null && treeView1.Nodes.Count > 0) 
          foreach (TreeNode node in treeView1.Nodes) restoreChecks(node);
  }

请注意,Node Names 必须是唯一的(应该如此)。

要在程序运行中保持状态,保存已检查节点的名称就足够了..

【讨论】:

  • 非常感谢@TaW,根据您之前的评论,我已经完成了您刚刚提出的所有操作,但我坚持认为即使我清除了树节点并重新添加了节点,节点也总是按顺序返回作为新的 Treenodes 但是你的代码示例救了我,因为我需要这行:this.treeView1.Sorted = false; 现在一切正常!再次感谢!
  • 假设节点永远不会改变,但它们的检查状态会改变,您认为将每个节点的检查状态保存为应用程序设置中的布尔值(用户范围)是否是个好主意?谢谢! :)
  • Sorted 是智能感知隐藏的属性。但是你在你的帖子中有它;-) - 嗯,我需要更多信息以获得建议。那么有一个 CheckState 吗? 1.你想让它在程序运行之间持久化吗? 2、节点数量会发生变化吗? 3.您是否添加其他任何内容,例如节点的标签? - (我实际上在自动取款机上睡着了,所以不要指望在接下来的几个小时内回复我......)
  • 感谢@TaW 是的,关于.sorted,我在原始帖子中有它,但不知道如何实现它,因为它不像我最初认为的那样工作......所以......现在我知道了。关于检查状态,是的,有检查状态并且节点的数量不会改变。我确实需要它在应用程序运行之间保持持久性。这就是为什么我认为这可能是一个很好的方法。再次感谢。
  • 顺便说一句,我相信我的问题会帮助很多其他人,因为我找不到我的问题的明确答案。有时反对票是错误的恕我直言,寻找此信息的人可能会因为反对票而拒绝。
猜你喜欢
  • 2012-01-03
  • 1970-01-01
  • 1970-01-01
  • 2015-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多