How to translate CodeBehind WPF Events; Event, Handler, EventSetter to MVVM pattern?

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

  •  26-10-2019
  •  | 
  •  

سؤال

I am trying to translate WPF CodeBehid events like Event, Handler, EventSetter to MVVM pattern. I am not allowed to use System.Windows.Controls since I am using MVVM. And I am also avoiding 3rd party library to solve this issue.

Can somebody explain how to convert the following CodeBehind Event Handler to MVVM Event-Handler? Please explain as much as you can while writing answer.

XAML Code

<DataGridCheckBoxColumn Header="Select" Binding="{Binding Path=IsSelected}"> 
  <DataGridCheckBoxColumn.CellStyle> 
    <Style TargetType="DataGridCell"> 
      <EventSetter Event="MouseLeftButtonUp" Handler="ApprovedMouseUp"></EventSetter> 
    </Style> 
  </DataGridCheckBoxColumn.CellStyle> 
</DataGridCheckBoxColumn> 

Code Behind

private void ApprovedMouseUp(object sender, MouseButtonEventArgs e) 
{ 
    if(sender is DataGridCell) 
    { 
        var temp = (sender as DataGridCell).Content; 
        if(temp is CheckBox) (temp as CheckBox).IsChecked = !(temp as CheckBox).IsChecked; 
    } 
} 
هل كانت مفيدة؟

المحلول

There are few thumb rules regarding MVVM....

  1. Your Models and ViewModles should not refer System.Windows.Controls namespace.
  2. Your Models and ViewModles should not handle events. Use ICommand interface for that.
  3. RoutedCommand is not valid in Models / ViewModels (due to point 2). Hence use DelegateCommand / RelayCommand

Having said that, all the above points are perfectly allowed if you have written an Attached Behavior in MVVM.

نصائح أخرى

You have a couple of choices:

  1. Attach the event handler in XAML but the only thing the event handler does is call into the view model passing in the appropriate arguments (it's important not to pass any GUI level items to the view model -- just the data necessary to perform the action)

  2. Use the EventToCommand behavior (showcased here) to attach an instance of an ICommand (from your view model) to an event in your view

As long as you're not trying to set these event handlers up in styles or templates I would recommend pursuing option #1 -- there is no iron law prohibiting you from using event handlers when convenient, as long as the view model is what actually performs all the work

Edit: Option #1

private void ApprovedMouseUp(object sender, MouseButtonEventArgs e) 
{ 
    if(sender is DataGridCell) 
    { 

        var checkBox= (sender as DataGridCell).Content as CheckBox; 
        if(checkBox != null) 
        {
            var viewModel = (MyViewModel)checkBox.DataContext;
            viewModel.ToggleApprovedStatus();
        }
    } 
} 

You can also use Caliburn Micro libraries to be able to attach a handler in ViewModel to an event in View.

Sample code:

 ...  xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"....

 <Button Content="Edit" DataContext="{Binding Path=VmInstance}" 
             cal:Message.Attach="[Event Click] = [Action EditFilter]" />
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top