Как можно правильно разделить представленный метод на две отдельные кнопки?
В общем-то, еще один вопрос по Формам от меня (предыдущий вопрос). Есть две LinkLabel кнопки и один TreeView. Первая кнопка добавляет основной узел, вторая подузел для выбранного узла. У самого же TreeView данные и отображение разделены, соответственно есть своя отдельная модель данных, а с ней метод FillVisualTree который вносит узлы с данными в сам список TreeView:
public void FillVisualTree(TreeNodeCollection tree)
{
foreach (var i in Items)
{
var node = new TreeNode { Text = i.Name, Tag = i };
foreach (var si in i.SubItems)
{
var subnode = new TreeNode { Text = si.Name, Tag = si };
node.Nodes.Add(subnode);
}
tree.Add(node);
}
}
Проблема в том, что этот метод заносит все узлы/подузлы разом, а у меня две отдельные кнопки, как выше уже писал, первая для добавления главного узла и вторая для добавления подузла к выбранному узлу.
Я попробовал разделить этот метод, чтобы он добавлял узлы по кускам.
Cначала занес в поля класса экземпляр класса "дерева", дабы иметь доступ вне метода:
private TreeNode node;
Далее создал метод FillVisualTreeRoot для добавления основного узла:
public void FillVisualTreeRoot(TreeNodeCollection tree)
{
node = new TreeNode();
foreach (var i in Items)
{
node.Text = i.Name;
node.Tag = i;
}
tree.Add(node);
}
И FillVisualTreeAnswer для его подузла:
public void FillVisualTreeAnswer(TreeNodeCollection tree)
{
var subnode = new TreeNode();
foreach (var i in Items)
{
foreach (var si in i.SubItems)
{
subnode.Text = si.Name;
subnode.Tag = si;
}
}
node.Nodes.Add(subnode);
}
Также внес в поля уже класса Формы экземпляр модели данных:
ItemModel item;
Потом в обработчике события кнопки для создания узла внес все данные и вызвал ранее созданный метод FillVisualTreeRoot, который должен добавлять узлы с данными в список:
private void NewRoot_Label_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
item = new ItemModel { Name = "Item1", Text = "Item1 Text" };
Model.Items.Add(item);
Model.FillVisualTreeRoot(Roots_TreeView.Nodes);
}
Все работает на отлично
Но у меня еще не задействована кнопка добавления подузлов.
В обработчике события второй кнопки для подузлов я также внес данные и вызвал второй метод FillVisualTreeAnswer и казалось бы все отлично, но он работает совсем иначе. Место того чтобы добавлять подузлы к ВЫБРАННЫМ узлам, он делает это только с последними созданными:
Немного подумав, я все таки догадываюсь в чем проблема, в общем экземпляре TreeNode nodе, который используется в двух методах в качестве добавления узлов в список. Так вот, как можно ПРАВИЛЬНО разделить метод FillVisualTree на две кнопки чтобы он ПРАВИЛЬНО создавал и разделял узлы/подузлы?
Ответы (1 шт):
В данном случае вы зря привязали добавление визуального элемента дерева к модели, хотя в этом, отчасти, моя вина, поправил предыдущий ответ.
Так как за отображение отвечает форма, то интерактивное добавление визуальных элементов следует оставить именно ей. Модифицируйте обработчики кликов по ссылке следующим образом:
private void NewRoot_Label_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
var item = new ItemModel { Name = "Item1", Text = "Item1 Text" };
Model.Items.Add(item);
treeView1.Nodes.Add(new TreeNode { Text = item.Name, Tag = item });
}
private void AddChild_Label_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
//эта проверка нужна, чтобы дочерние узлы добавлялись только в выбранный корень
//и не добавлялись в дочерние
if (treeView1.SelectedNode?.Tag is ItemModel item)
{
var subItem = new SubItemModel { Name = "Item1", Text = "Item1 Text", Parent = item };
item.SubItems.Add(subItem);
treeView1.SelectedNode?.Nodes.Add(new TreeNode { Text = subItem.Name, Tag = subItem });
//ну и сразу развернем узел в который добавили элемент
treeView1.SelectedNode?.Expand();
}
}
К большому сожалению, реализация штатного TreeView в WinForms довольно "топорная" и не поддерживает автоматическую привязку данных через свойство DataSource, которое у него просто отсутствует в отличие от, например, ListBox или ComboBox. Поэтому добавление, удаление и начальную генерацию узлов данного контрола приходится делать руками.
Также стоит посмотреть в сторону классов BindingList<T> и BindingSource.
Есть неплохая статья по основам привязки данных, только читать надо очень внимательно, при беглом просмотре можно упустить важные детали.

