0

I have a GridView which is bound to the property Sessions on my viewmodel. When a new item is selected in the GridView I want this to trigger navigation to a new view. The Sessions property is a list of SessionViewModel but this has several subclasses which have independent corresponding views. I have this currently in my view code behind:

this.BindCommand(ViewModel, x => x.SessionNavigateCommand, x => x.SessionsGridView, "ItemClick");

This fires back to the SessionNavigateCommand on my viewmodel, this is of type IReactiveCommand. I want to subscribe to the command like so:

SessionNavigateCommand.Subscribe(x => HostScreen.Router.Navigate.Execute(x));

But the event args wrap the actually viewmodel that I need and I don't want to pollute my viewmodel with view specific code.

JFoulkes
  • 2,429
  • 1
  • 21
  • 24

1 Answers1

0

I've had similar design issues in a Navigation based WPF application. My solution was to define Action commands on the ViewModel and Navigation commands on the View, or for global Navigations as commands on the NavigationWindow that hosts everything.

In some cases, e.g. where an interaction results in both an action and a navigation, I have my View level command calling my ViewModel command and then Navigating to finish the action.

I'm not sure I'm entirely happy with this method, while it is successful in achieving my goals it just feels wrong. If you find a better solution I'd be very interested

Example button resulting in a navigation

<Button Style="{StaticResource HyperLinkButtonStyle}"                 
  Command="{Binding GoCurrentCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=View:MainWindow, AncestorLevel=1}}"
  Content="Details"/>

Normal button with action

<Button
  Style="{StaticResource HyperLinkButtonStyle}" 
  Command="{Binding CompleteCommand}"
  Content="Complete"/>

Here's an example view level command with delegation to the ViewModel (note the use of ReactiveUI, so the syntax might not be quite what you are used to)

public class MainWindow : NavigationWindow
{
  ...
  //This defines when the command can be run
  this._completeCommand = new ReactiveCommand(((SolutionViewModel)DataContext).CompleteCommand.CanExecuteObservable); 
  //This defines what to do when the command is run
  this._completeCommand.Subscribe( 
    _ =>
    {
      ((SolutionViewModel)DataContext).CompleteCommand.Execute(null);
      this.NavigationService.Navigate(new IntentionsListPage { DataContext = this.DataContext });
    });
AlSki
  • 6,868
  • 1
  • 26
  • 39