문제

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