Как удалить все, кроме отмеченных узлов и их родителей в виде дерева? - PullRequest
1 голос
/ 01 июня 2011

У меня есть TreeView, который содержит любое количество узлов. Пользователи могут проверить любой из узлов в TreeView и, как только они нажмут кнопку, я хочу удалить все, кроме проверенных узлов и их родителей. У меня есть кнопка все настройки, и она вызывает метод, который должен обрезать узлы, проблема, которую я имею, заключается в логике обрезки. Даже псевдокод будет полезен. Я знаю, что он должен быть рекурсивным и должен начинаться с самых внешних узлов и проходить мой путь вверх, но я не могу придумать рекурсию.

Мне все равно, подрезает ли он TreeView напрямую или создает новый List<TreeNode>, к которому я могу привязаться.

Любая помощь будет принята с благодарностью, спасибо.

Решение: Решение InBetween исправило мою логическую проблему, но была еще одна проблема. Вы должны удалить узлы из их родителя. Так что вы не можете просто пойти и сделать TreeView.Remove(node), вы должны сделать ParentNode.ChildNodes.Remove(node).

Ответы [ 3 ]

2 голосов
/ 01 июня 2011

Мне пришлось сделать что-то подобное, где, если щелкнуть ребенка, родительский выбор был автоматически выбран.Поэтому я думаю, что это может помочь, так как сначала будут выбраны все родители, а затем вы сможете очистить, выбрав выбранное (сверху):

    private void RecursiveCheckNodesDown(TreeNodeCollection tree, bool checkedFlag)
    {
        if (tree != null) 
            foreach (TreeNode node in tree)
                RecursiveCheckNodesDown(node.Nodes, node.Checked = checkedFlag);
    }

    private void RecursiveCheckNodesUp(TreeNode node, bool checkedFlag)
    {
        if( node != null )
            RecursiveCheckNodesUp(node.Parent, node.Checked = checkedFlag);
    }

    private void SomeTreeBeginUpdate()
    {
        SomeTree.BeginUpdate();
        SomeTree.AfterCheck -= SomeTree_AfterCheck;
    }

    private void SomeTreeEndUpdate()
    {
        SomeTree.AfterCheck += SomeTree_AfterCheck;
        SomeTree.EndUpdate();
    }

    private void SomeTree_AfterCheck(object sender, TreeViewEventArgs e)
    {
        SomeTreeBeginUpdate();
        RecursiveCheckNodesDown(e.Node.Nodes, e.Node.Checked);
        if( e.Node.Checked )
            RecursiveCheckNodesUp(e.Node.Parent, e.Node.Checked);
        SomeTreeEndUpdate();
    }

    this.SomeTree.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.SomeTree_AfterCheck);
2 голосов
/ 01 июня 2011

Иногда помогает рассмотрение проблемы с другой точки зрения.

Почему бы вам сначала не изменить логику того, как дерево управляет проверкой элементов, если это возможно:

Если пользователь проверяет элемент, вы не удалите ни элемент, ни его родителей. Поэтому, когда пользователь проверяет элемент, проверяйте каждый элемент вверх по дереву, пока не дойдете до корневого элемента выбранного элемента. Это легко реализовать.

Теперь, когда вы подрезаете, вам нужно просто пройти по дереву (начиная с корневых элементов и спускаясь по дереву) в поисках непроверенных элементов. Вы можете удалить их и, следовательно, все предметы, висящие на нем, не глядя, есть ли выбранные предметы в этой ветви.

Возможно, эта опция недопустима из-за ваших требований.

0 голосов
/ 01 июня 2011

это можно сделать, реализовав поиск в глубину ...

что-то вроде

//pseudocode
bool prune(treenode t)
{
   bool mayNotDeleteThisNode=t.isChecked;
   foreach(treenode c in t.childnodes)
   {
      if(prune(c)) mayNotDeleteThisNode=true;
   }

   if(!mayNotDeleteThisNode)
   {
      delete(t)
   }

   return mayNotDeleteThisNode;
}
...