【问题标题】:How to translate CodeBehind WPF Events; Event, Handler, EventSetter to MVVM pattern?如何翻译 CodeBehind WPF 事件;事件、处理程序、事件设置器到 MVVM 模式?
【发布时间】:2011-12-10 14:12:30
【问题描述】:

我正在尝试将 WPF CodeBehid 事件(如 Event、Handler、EventSetter)转换为 MVVM 模式。我不允许使用 System.Windows.Controls,因为我使用的是 MVVM。而且我也在避免使用 3rd 方库来解决这个问题。

有人可以解释如何将以下 CodeBehind 事件处理程序转换为 MVVM 事件处理程序吗?请在写答案时尽可能多地解释。

XAML 代码

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

代码隐藏

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; 
    } 
} 

【问题讨论】:

    标签: wpf events mvvm eventargs


    【解决方案1】:

    您还可以使用Caliburn Micro 库将 ViewModel 中的处理程序附加到 View 中的事件。

    示例代码:

     ...  xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"....
    
     <Button Content="Edit" DataContext="{Binding Path=VmInstance}" 
                 cal:Message.Attach="[Event Click] = [Action EditFilter]" />
    

    【讨论】:

      【解决方案2】:

      关于 MVVM 的经验法则很少......

      1. 您的 ModelsViewModles 不应引用 System.Windows.Controls 命名空间。
      2. 您的ModelsViewModles 不应处理事件。为此使用ICommand 接口。
      3. RoutedCommand 在模型/视图模型中无效(由于第 2 点)。因此使用DelegateCommand / RelayCommand

      话虽如此,如果您在 MVVM 中编写了 Attached Behavior,上述所有点都是完全允许的

      【讨论】:

      • 我最大的挑战是将 CodeBehind 事件转换为 MVVM 模式。如何在需要检查 Sender 是否为 DataGrid 的地方转换 Sender?以同样的方式,我如何验证它是否是复选框?我如何挂钩事件,处理程序?等注意:我避免使用 3rd 方库来解决此问题。
      • 嘿 Shai,附加行为在这里为您提供帮助。请参阅我的另一篇文章正是这样做的。在这个例子中,我处理了组合框的 SelectionChanged() 事件,以根据 MVVM 中的特定条件 cancel 选择 ...stackoverflow.com/questions/7800032/…
      【解决方案3】:

      你有几个选择:

      1. 在 XAML 中附加事件处理程序,但事件处理程序唯一要做的就是调用视图模型并传入适当的参数(重要的是不要将任何 GUI 级别的项传递给视图模型——只传递数据执行操作所必需的)

      2. 使用 EventToCommand 行为(此处展示)将 ICommand 实例(来自您的视图模型)附加到您视图中的事件

      只要您不尝试在样式或模板中设置这些事件处理程序,我建议您采用选项#1——没有铁律禁止您在方便时使用事件处理程序,只要视图模型是实际执行所有工作的原因

      编辑:选项 #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();
              }
          } 
      } 
      

      【讨论】:

      • 我发现我需要使用以下 3rd-party 库来使用 EventToCommand。 1) GalaSoft.MvvmLight.dll,2)GalaSoft.MvvmLight.Extras.dll 除了 System.Windows.Interactivity.dll。由于我试图避免使用第三方库,我可以举个 option-1 的例子吗?
      • 如何将上面的 Option#1 示例代码转换为 MVVM 模式?
      • @Shai 是 MVVM 模式。该事件处理程序位于 GUI 背后的代码中,并调用视图模型的 ToggleApprovedStatus() 方法
      • 我还有两个问题。问题 #1:我仍然需要单击两次,第一次单击选择单元格,第二次单击选中复选框。问题 #2:我不明白 MyViewModel 对复选框的引用将如何实现。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多