Ben Straub
Ben Straub

Reputation: 5776

Multi-layer "Expand All" for expanders?

I'm writing an MVVM configuration interface, and I'm trying to implement an expand/collapse all function that applies to all the views.

The top-level ViewModel is a homogeneous collection of other ViewModels, which is bound to an ItemsControl in the view. Each of these child ViewModels has a number of dependent ViewModels, each of which is bound to a ContentControl in the View. Visually, this takes the form a a set of expanders (say, 3 of them), each of which has 4-6 expanders hidden inside.

I've tried top-down search methods. Since the top-level expanders are collapsed, their child expanders don't even exist until they are shown for the first time (Caliburn.Micro is doing view location for them when they're first asked for), and the "expand all" action only expands the first level.

The logical tree isn't any help either. The top-level ItemsControl's Items property actually contains objects of my ViewModel type, so I can't look inside them for expanders.

I've thought of managing this at the ViewModel level, but adding an IsExpanded property to all of the VMs and setting it using some global manager seems messy. There's no other reason for the VM to know which expanders are expanded.

What's the best way of handling this? Is there some attached-property binding trick I could pull?

Upvotes: 0

Views: 392

Answers (1)

Rhyous
Rhyous

Reputation: 6680

Your ViewModel should have a function that expands itself and calls the same function in its children.

public abstact class BaseItem
{
   public List<BaseItem> Children;

   public virtual void SetSelfAndChildrenExpandedState(bool inState)
   {
      // Expand Self
      IsExpanded = inState;
      // Expand Children
      foreach (BaseItem i in Children)
      {
          i.SetSelfAndChildrenExpandedState(inState);
      }
   }

   public bool IsExpanded { get; set; }
}

Now you just have to hook up your "expand all" action to call SetSelfAndChildrenExpandedState() with the appropriate parameter.

That might work for you...give it a thought.

Upvotes: 1

Related Questions