Conditionally show WPF Treeview levels

144 Views Asked by At

I'm using a TreeView and HierarchicalDataTemplates in WPF and need to use some logic to decide which level of my data structure should be the root node in the tree.

My data structure that the TreeView is bound to is something like this:

|Root
|---|Sublevel1
|------|SubLevel2
|---------|Sublevel3

Based on the role that the user is logged in as, I need to make the root of the tree one of the sublevels, for example:

  • If I'm an Admin, show the entire tree as listed above.
  • If I'm a Power User, start the tree at Sublevel1.
  • If I'm a Normal User, show the tree starting at SubLevel2.

What would be the best approach for doing this? I basically have 4 user roles so I've toyed with the idea of simply creating 4 versions of the tree and selectively showing the correct one based on the user role, but I'm sure there's a better way.

1

There are 1 best solutions below

1
On

If the tree views essentially display the same data, then do not create four separate tree views. That is redundant, keep it DRY. Populate a single TreeView according to the role that is curretly active.

Let us assume that you have a collection in your view model that contains the hierarchical tree data structure. Usually there is a root node or a collection of nodes of a common node data type, which contains an ObservableCollection of child nodes.

private MyNodeType _root;

This root contains the hierarchical data. Expose a property that represents the top level collection of your tree data structure for binding to ItemsSource of your single TreeView.

private ObservableCollection<MyNodeType> _roles;
public ObservableCollection<MyNodeType> Roles
{
   get => _roles;
   set
   {
      if (_roles == value)
         return;

      _roles = value;
      OnPropertyChanged();
   }
}

It is important to implement INotifyPropertyChanged, if you can change roles at runtime, because then you would assign a different collection and without raising the PropertyChanged event, the bindings and therefore the associated controls would not update their value.

Now, if you change the role in your application, you can search for matching role in your _root member and directly assign the corresponding child collection to the Roles property, e.g. Sublevel1 (assuming that the child collection property is Children).

Roles = _root.Children;

Of course you could also remove the _root backing property and load, search and assign the right collection on each user change, that depends on your requirements.