How to implement menuitems that depend on current selection in WPF MVVM explorer-like application

StackOverflow https://stackoverflow.com/questions/2525759

  •  22-09-2019
  •  | 
  •  

Question

I am new to WPF and MVVM, and I am working on an application utilizing both. The application is similar to windows explorer, so consider an app with a main window with menu (ShellViewModel), a tree control (TreeViewModel), and a list control (ListViewModel). I want to implement menu items such as Edit -> Delete, which deletes the currently selected item (which may be in the tree or in the list).

I am using Josh Smith's RelayCommand, and binding the menuitem to a DeleteItemCommand in the ShellViewModel is easy. It seems like implementing the DeleteItemCommand, however, requires some fairly tight coupling between the ShellViewModel and the two child view models (TreeViewModel and ListViewModel) to keep track of the focus/selection and direct the action to the proper child for implementation. That seems wrong to me, and makes me think I'm missing something.

Writing a focus manager and/or selection manager to do the bookkeeping does not seem too hard, and could be done without coupling the classes together. The windowing system is already keeping track of which view has the focus, and it seems like I'd be duplicating code.

What I'm not sure about is how I would route the command from the ShellViewModel down to either the ListViewModel or the TreeViewModel to do the actual work without making a mess of the code. Some day, the application will be extended to include more than two children, and I want the shell to be as ignorant of the children as possible to make that extension as painless as possible.

Looking at some sample WPF/MVVM applications (Karl Shifflett's CipherText, Josh Smith's MVVM Demo, etc.), I haven't seen any code that does this (or I didn't understand it).

Regardless of whether you think my approach is way off base or I'm just missing a small nuance, please share your thoughts and help me get back on track. Thanks!

Was it helpful?

Solution

There are some inherent issues with Josh Smith's implementation of MVVM. Take a look at Ward Bell's post on the subject: http://neverindoubtnet.blogspot.com/2010/03/mvvm-josh-smiths-way.html. You may want to take a look at some alternative MVVM frameworks such as Caliburn that take a ViewModel first approach and break this coupling.

OTHER TIPS

The RelayCommand is just a way to get a command in your ViewModel that can be bound to your View.

I think I would be inclined to step back from all of the different MVVM architectural variations and sample apps, and just use good old OOD. Why not have a ViewModel base class of some sort (ie, DetailsViewModelBase) for TreeViewVm and ListViewVm. Put a DeleteCommand in there with CanDelete and Delete methods that have as much implementation as the subclasses share (or abstract if none), and a SelectedItem as well. Then bind the SelectedItem to the controls similar to the xaml below:

    <ListView AlternationCount="2" MinHeight="250" MaxHeight="400" 
          ItemsSource="{Binding Projects.View}" 
          IsSynchronizedWithCurrentItem="True"
          SelectedItem="{Binding SelectedProject, Mode=TwoWay}"
          behaviors:SelectionBehavior.DoubleClickCommand="{Binding PickCommand}"
          ItemContainerStyle="{StaticResource listingRowStyle}"
                      >

The key bindings being SelectedItem and IsSynchronizedWithCurrentItem.

HTH,
Berryl

I found a blog post by Kent Boogaart that describes what he calls an ActiveAwareCommand. This seems to do what I was looking for, although I haven't yet tried it. A comment on the post mentions Prism's IActiveAware as having similar behavior.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top