0
votes

I have read some thread about how to work on WPF ListView command binding.

Passing a parameter using RelayCommand defined in the ViewModel Binding Button click to a method Button Command in WPF MVVM Model How to bind buttons in ListView DataTemplate to Commands in ViewModel?

All of them suggest write the logic code inside ViewModel class, for example:

  public RelayCommand ACommandWithAParameter
  {
     get
     {
        if (_aCommandWithAParameter == null)
        {
           _aCommandWithAParameter = new RelayCommand(
               param => this.CommandWithAParameter("Apple")
               );
        }

        return _aCommandWithAParameter;
     }
  }

  public void CommandWithAParameter(String aParameter)
  {
     String theParameter = aParameter;
  }

It is good practice or anyway so I can move the CommandWithAParameter() out of the ViewModel?

1
Possible duplicate of Why RelayCommandRekshino
Do you want to move it into Code Behind (View) or into the Model?Daniel W.
Since my concept come from winform and ASP.NET MVC world, I considering move to the view's code behind (MainWindow.xaml.cs), and ViewModel inherit the MainWindow class to execute the CommandWithAParameter(), however ViewModel inherit View seem not make sense. Maybe I create something like Service Layer like ASP.NET MVC is more elegant?Cheung

1 Answers

1
votes

In principle, MVVM application should be able to run to its full potential without creating the views. That's impossible, if some parts of your logic are in View classes.

On top of that, ICommand has CanExecute, which will autamagically disable buttons, menu items etc. if the command should not be run.

I understand why with basic RelayCommand implementation it can be hard to see the benefits, but take a look at ReactiveCommand samples.

ReactiveCommand handles async work very well, even disabling the button for the time work is done and enabling it afterwards.

Short example: you have a login form. You want to disable the login button if the username and password are empty.

Using commands, you just set CanExecute to false and it's done.

Using events, you have manualy disable/enable the button, remember that it has to be done in Dispatcher thread and so on - it gets very messy if you have 5 buttons depending on different properties.

As for ListView, commands are also usefull - you can bind current item as command parameter:

<ListView ItemsSource="{Binding MyObjects}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <DockPanel>
                      <!-- change the context to parent ViewModel and pass current element to the command -->
                <Button DockPanel.Dock="Right" Command="{Binding ElementName=Root, Path=ViewModel.Delete}" CommandParameter="{Binding}">Delete</Button>

                <TextBlock Text="{Binding Name}"/>
            </DockPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>