C # TreeView design - best way to display tree structure?

I am trying to use TreeView to display a tree structure of objects. I have a tree of four types of objects, Company (root node), City, Shop and Employee.

The interface is designed to add / remove cities / stores / employees, so the TreeView should be updated to reflect any changes.

I am wondering how to get a TreeView to display a tree structure and get updates when changing.

I think that a company object should have events like company.CityAdded and company.CityRemoved, then which shell that I exchanged TreeView responds to these events? When the TreeView is created, there will be a node for the city / store / employee. Each node could respond to the node events that it represents in the tree.

Is this the right idea? Or is there a better method?

+4
source share
5 answers

I just wanted to add that if WPF is an option for this, it becomes incredibly simple using hierarchical data binding and observable collections. It basically does all the events for event processing for you and allows you to simply interact with your business objects.

+2
source

You are on the right track about the concept of listening for events (this is the standard publisher / subscriber template).

For the actual treeview update, I tend to have two methods: AddOrUpdateTreeItem and RemoveTreeItem . The add or update method does what it says, searches for the tree element (based on the path), and updates it or adds it. Of course, if the model is updated in a thread other than the one on which the form was created, you will need to march the call using Control.BeginInvoke() .

This approach can be a little slow if you populate the complete tree in form_load or something like that, so you may have a different method for the original aggregate and use the concept described here for future updates.

I am doing the same for listviews, here is a typical example. The main difference when adding a tree element is that you may need to add parent nodes to add a node query, which makes it a bit recursive. Give it a try.

 private void AddOrUpdateListItem(DomainModelObject item) { ListViewItem li = lvwListView.Items[GetKey(item)]; if (li == null) { li = new ListViewItem { Name = GetKey(item), Tag = item }; li.SubItems.Add(new ListViewItem.ListViewSubItem()); li.SubItems.Add(new ListViewItem.ListViewSubItem()); li.SubItems.Add(new ListViewItem.ListViewSubItem()); li.ImageIndex = 0; lvwListView.Items.Add(li); } li.Text = [Itemtext]; li.SubItems[1].Text = [Itemtext]; li.SubItems[2].Text = [Itemtext]; li.SubItems[3].Text = [Itemtext]; } 

Here is an example of how BeginInvoke() can be implemented:

 public class MyForm : Form { ... void data_Changed(object sender, DataChangedEventArgs e) { if (this.InvokeRequired) { this.BeginInvoke(new EventHandler<DataChangedEventArgs>(data_Changed), sender, e); return; } AddOrUpdateListItem(e.DataItem); } ... } 
+1
source

You seem to be on the right track. I should have done something like this, a few pointers that I would like to share:

  • Save the reference to the object in the property of the TreeNode tag.

  • Give each Treenode a unique name that can easily identify an object, for example: hashcode of an object, company identifier, etc.

This way you can easily find and update the TreeNode when the state of the object changes. And when the user selects node, you can grab the object that it represents from the Tag property.

Good luck.

+1
source

Instead...

  • Business objects subscribe to user interface events
  • Commands Update User Interface
  • Business objects are updated when the user interface is updated.

... you can also do it the other way around (i.e., the teams update the tree of business objects, which leads to a corresponding update of the user interface).

0
source

Part of the key to the publication / subscription template for updates is how to wrap information about what to do when the event fires.

When an object representing "Store X" is updated with a new name and fires an event to report this, which object uses the event?

Similarly, when City Y is added, which object should be notified of the creation?

One general approach is to have some kind of large uber-manager class that handles the whole process - it subscribes to all events and does everything.

Another approach that I used for a good effect is to create much simpler wrapper / coordinator objects that process only one part of the puzzle. I usually suffix the name of these classes with " Editor ".

So, you can have the CityEditor class, the constructor of which accepts both the City object and the TreeNode that represents this object. CityEditor will subscribe to events for both the City object and the TreeNode , and will take care of filling the TreeNode title and selecting an icon.

When the City object is updated, CityEditor responds to the triggered event by updating the TreeNode . When the City object is deleted, CityEditor ensures that the node is removed from the Treeview .

When a new Store object is added to City , CityEditor can take care of creating a StoreEditor to coordinate updates at this level. Similarly, if Employee added to the Store , the Employee instance handles Treeview updates.

0
source

All Articles