Здравствуйте!
Есть следующая проблема.
Имеется TreeView с огромным количеством узлов на разных уровнях. Класс узла — наследник от TreeNode со своими полями.
public class MyTreeNode: TreeNode
{
public string myStringField;
...
}
Хочу сгруппировать узлы верхнего уровня по myStringField, перенести их целиком с потомками из корня дерева в новые узлы вот так
/*было*/
|-string1 node1
|-string1 node2
|-string2 node3
|-string1 node4
|-string2 node5
/*стало*/
-string1
|-node1
|-node2
+-node4
-string2
|-node3
+-node5
Где stringN — значения полей myStringField,
каждый nodeN содержит кучу потомков.
Пробема в том, что если делать такую группировку, клонируя узлы, добавляя их в группирующий узел, и удаляя из корня дерева, получается очень медленно. А мне нужно, всего-то изменить ссылку на родительский узел! Но TreeNode.Parent — только для чтения

Как быть? Есть какой-то способ поменять эту самую ссылку (TreeNode.Paren)?
Спасибо!
/****Приложение :)****/
Вот, что я делаю:
private void GroupImplementations(TreeNodeCollection tnc)
{
int i = 0;
int j;
if (null != tnc && tnc.Count > 0)
while (i < tnc.Count-1 && !string.IsNullOrEmpty(((SostavTreeNode)tnc[i]).myStringField))
{
bool biRemove = false;
MyTreeNode node_i = (MyTreeNode)tnc[i];
j = i+1;
while (j<tnc.Count)
{
MyTreeNode node_j = (MyTreeNode)tnc[j];
if (node_i.myStringField == node_j.myStringField)
{
int index = GetIndexOfGroupingNode(tnc, node_i.myStringField);//ищет индекс узла в TreeNodeCollection, у которого node.Name==myStringField
if (-1 == index) //создаём группирующий узел
{
MyTreeNode groupingNode = new MyTreeNode();
groupingNode.Name = node_i.myStringField;
groupingNode.Text = node_i.myStringField;
groupingNode.Nodes.AddRange(new TreeNode[] { (MyTreeNode)node_i.Clone(), (MyTreeNode)node_j.Clone() }); //медленно! :(
tnc.Add();
}
else //добавляем к уже существующему группирующему узлу
{
tnc[index].Nodes.Add((MyTreeNode)node_j.Clone()); //медленно! :(
}
node_j.Remove(); //медленно! :(
biRemove = true;
}
else
j++;
}
if (biRemove)
{
node_i.Remove(); //медленно! :(
biRemove = false;
}
else
i++;
}
}
Здравствуйте, HAN-BRATAN, Вы писали:
HB>this.SuspendLayout();
HB>this.ResumeLayout(false);
HB> — посмотри в этом направлении, что-то должно быть такое и и в TreeView
В доке к
SuspendLayout чётко сказано, когда её следует вызывать:
The SuspendLayout and ResumeLayout methods are used in tandem to suppress multiple Layout events while you adjust multiple attributes of the control. For example, you would typically call the SuspendLayout method, then set the Size, Location, Anchor, or Dock properties of the control, and then call the ResumeLayout method to enable the changes to take effect.
Здравствуйте, voiger, Вы писали:
V>Есть следующая проблема.
V>Пробема в том, что если делать такую группировку, клонируя узлы, добавляя их в группирующий узел, и удаляя из корня дерева, получается очень медленно.
TreeView.BeginUpdate();
try {
// Перестановки
} finally {
TreeView.EndUpdate();
}//try
здесь
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, voiger, Вы писали:
V>>Есть следующая проблема.
V>>Пробема в том, что если делать такую группировку, клонируя узлы, добавляя их в группирующий узел, и удаляя из корня дерева, получается очень медленно.
_FR>_FR>TreeView.BeginUpdate();
_FR>try {
_FR> // Перестановки
_FR>} finally {
_FR> TreeView.EndUpdate();
_FR>}//try
_FR>
_FR>здесь
Спасибо, помогло

Думал, если TreeView.Visible == false, то BeginUpdate()/EndUpdate() и необязательно вызывать

. А получается вот что:
/*было*/
TreeNode.Remove() 3467 msec
TreeNode.Clone() 495 msec
/*стало*/
TreeNode.Remove() 2162 msec
TreeNode.Clone() 450 msec
Это на тестовом примере небольшого размера.
Но вопрос остаётся открытым. Clone()-то копирует полностью весь узел со всеми полями и потомками, а почему Remove() так долго работает — вообще загадка. Можно как-то TreeNode.Parent() поменять?