Привязка данных TreeView к RichTextBox
Я тут создаю диалоговый редактор для игры и у меня появилась проблема, которую я никак не могу решить. Как можно реализовать подобную вещь:
- Есть два вместе находящихся элемента на форме RichTextBox и один TreeView.
- В TreeView с помощью кнопки добавляются узлы.
- При нажатии на узел активируется первый RichTextBox, при нажати на его подузел второй RichTextBox.
- В данный RichTextBox можно что-то вписать и это сохраниться в выбранном узле/подузле (не в двух сразу).
- Если юзер нажмет на другой узел или их подузел, то RichTextBox очистится, но при повторном нажатии на тот прошлый узел те, ранее вписанные данные, вновь появятся в RichTextBox.
- И так можно привязывать данные к любому выбранному узлу.
- Данные каждого узла я смогу получить через код в будущем.
Меня больше всего интересует 4,5,6 и 7 пункт. Остальное я уже реализовал, а вот с этими я даже не представляю как. Я знаю про существование Tag у узлов, но это не дает мне никакого представления реализации подобного. Заранее спасибо за ответ.
Ответы (1 шт):
В общем-то ваша задача решается довольно просто если разделить данные и их отображение. Поэтому для начала сделаем простую модель данных для демонстрации (под свои данные адаптируете самостоятельно):
public class ItemModel
{
public string Name { get; set; }
public List<SubItemModel> SubItems { get; } = new List<SubItemModel>();
public string Text { get; set; }
}
public class SubItemModel
{
public string Name { get; set; }
public ItemModel Parent { get; set; }
public string Text { get; set; }
}
//Обращаю внимание на необходимость реализации INotifyPropertyChanged
//для правильной работы биндингов
public class TreeModel : INotifyPropertyChanged
{
//выбранные значения заполняем пустышками
private ItemModel _selectedItem = new ItemModel();
private SubItemModel _selectedSubItem = new SubItemModel();
public List<ItemModel> Items { get; } = new List<ItemModel>();
public ItemModel SelectedItem
{
get => _selectedItem;
set
{
_selectedItem = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedItem)));
}
}
public SubItemModel SelectedSubItem
{
get => _selectedSubItem;
set
{
_selectedSubItem = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedSubItem)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
//Для примера заполним модель данными в конструкторе, но разумеется это нужно
//делать в более подходящем месте вашей программы
public TreeModel()
{
var item = new ItemModel { Name = "Item1", Text = "Item1 Text" };
item.SubItems.Add(new SubItemModel {
Name = "SubItem11", Text = "SubItem11 Text", Parent = item });
item.SubItems.Add(new SubItemModel {
Name = "SubItem12", Text = "SubItem12 Text", Parent = item });
Items.Add(item);
item = new ItemModel { Name = "Item2", Text = "Item2 Text" };
item.SubItems.Add(new SubItemModel {
Name = "SubItem21", Text = "SubItem21 Text", Parent = item });
item.SubItems.Add(new SubItemModel {
Name = "SubItem22", Text = "SubItem22 Text", Parent = item });
Items.Add(item);
}
}
Подготовительные работы закончены, теперь немного непривычной магии в коде формы:
public partial class Form1 : Form
{
private readonly TreeModel Model = new TreeModel();
public Form1()
{
InitializeComponent();
FillVisualTree(treeView1.Nodes);
treeView1.AfterSelect += TreeView1_AfterSelect;
//добавляем двусторонние привязки к модели с возможностью обновления данных
richTextBox1.DataBindings.Add(
new Binding("Text", Model, "SelectedItem.Text", false, DataSourceUpdateMode.OnValidation, ""));
richTextBox2.DataBindings.Add(
new Binding("Text", Model, "SelectedSubItem.Text", false, DataSourceUpdateMode.OnValidation, ""));
}
private void TreeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
switch(e.Node.Tag)
{
case ItemModel i:
Model.SelectedItem = i;
//когда выбран корневой элемент подставляем пустышку в дочерний
Model.SelectedSubItem = new SubItemModel();
break;
case SubItemModel si:
Model.SelectedSubItem = si;
Model.SelectedItem = si.Parent;
break;
}
}
//Вспомогательный метод для заполнения TreView
private void FillVisualTree(TreeNodeCollection tree)
{
foreach (var i in Model.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);
}
}
}
Код дизайнера с добавлением элементов формы остался за кадром и не представляет интереса.