MVVM - View / ViewModel通信

在本章中,我们将学习如何向MVVM应用程序添加交互性以及如何干净地调用逻辑.您还将看到所有这些都是通过维护松散耦合和良好的结构来完成的,这是MVVM模式的核心.要理解这一切,首先让我们了解命令.

通过命令查看/ViewModel通信

命令模式已有详细记录并经常使用几十年的设计模式.在这种模式中有两个主要的角色,即调用者和接收者.

View and ViewModel Communication

Invoker

  • 调用程序是一段可以执行命令逻辑的代码.

  • 通常,它是用户在UI框架环境中与之交互的UI元素.

  • 它可能只是应用程序中其他地方的另一块逻辑代码.

Receiver

  • 接收者是在调用者触发时执行的逻辑.

  • 在MVVM的上下文中,接收器通常是ViewModel中需要调用的方法.

在这些之间二,你有一个障碍层,这意味着调用者和接收者不必明确地了解彼此.这通常表示为向调用者公开的接口抽象,并且该接口的具体实现能够调用接收者.

让我们看一个您将学习的简单示例命令以及如何使用它们在View和ViewModel之间进行通信.在本章中,我们将继续上一章中的相同示例.

在StudentView.xaml文件中,我们有一个ListBox,用于连接ViewModel中的学生数据.现在让我们添加一个用于从ListBox中删除学生的按钮.

重要的是在按钮上使用命令非常简单,因为它们具有连接到ICommand的命令属性.

因此,我们可以在ViewModel上公开一个具有ICommand的属性,并通过按钮的命令属性绑定它,如下面的代码所示.

<Button Content = "Delete"    Command = "{Binding DeleteCommand}"    HorizontalAlignment = "Left"    VerticalAlignment = "Top"    Width = "75" />

让我们在你的项目中添加一个新类,它将实现ICommand接口.以下是ICommand接口的实现.

using System; using System.Windows.Input;namespace MVVMDemo {    public class MyICommand : ICommand {       Action _TargetExecuteMethod;       Func<bool> _TargetCanExecuteMethod;      public MyICommand(Action executeMethod) {         _TargetExecuteMethod = executeMethod;       }      public MyICommand(Action executeMethod, Func<bool> canExecuteMethod){          _TargetExecuteMethod = executeMethod;         _TargetCanExecuteMethod = canExecuteMethod;       }      public void RaiseCanExecuteChanged() {          CanExecuteChanged(this, EventArgs.Empty);       }      bool ICommand.CanExecute(object parameter) {          if (_TargetCanExecuteMethod != null) {             return _TargetCanExecuteMethod();          }          if (_TargetExecuteMethod != null) {             return true;          }          return false;       }      // Beware - should use weak references if command instance lifetime          is longer than lifetime of UI objects that get hooked up to command       // Prism commands solve this in their implementation       public event EventHandler CanExecuteChanged = delegate { };      void ICommand.Execute(object parameter) {          if (_TargetExecuteMethod != null) {            _TargetExecuteMethod();          }       }    } }

如您所见,这是一个简单的委托实现ICommand我们有两个委托给一个executeMethod,一个给canExecuteMethod,可以在构造时传入.

在上面的实现中,有两个重载的构造函数,一个只用于executeMethod和对于executeMethod和我都可以执行一个canExecuteMethod.

让我们在StudentView Model类中添加MyICommand类型的属性.现在我们需要在StudentViewModel中构造一个实例.我们将使用带有两个参数的MyICommand的重载构造函数.

public MyICommand DeleteCommand { get; set;} public StudentViewModel() {    LoadStudents();    DeleteCommand = new MyICommand(OnDelete, CanDelete); }

现在添加OnDelete和CanDelete方法的实现.

private void OnDelete() {    Students.Remove(SelectedStudent); }private bool CanDelete() {    return SelectedStudent != null;  }

我们还需要添加一个新的SelectedStudent,以便用户可以从ListBox中删除Selected Item.

private Student _selectedStudent; public Student SelectedStudent {    get {       return _selectedStudent;    }    set {       _selectedStudent = value;      DeleteCommand.RaiseCanExecuteChanged();    } }

以下是ViewModel类的完整实现.

using MVVMDemo.Model; using System.Collections.ObjectModel; using System.Windows.Input; using System;namespace MVVMDemo.ViewModel {    public class StudentViewModel {       public MyICommand DeleteCommand { get; set;}       public StudentViewModel() {          LoadStudents();          DeleteCommand = new MyICommand(OnDelete, CanDelete);       }      public ObservableCollection<Student> Students {          get;          set;       }      public void LoadStudents() {          ObservableCollection<Student> students = new ObservableCollection<Student>();         students.Add(new Student { FirstName = "Mark", LastName = "Allain" });          students.Add(new Student { FirstName = "Allen", LastName = "Brown" });          students.Add(new Student { FirstName = "Linda", LastName = "Hamerski" });          Students = students;       }      private Student _selectedStudent;       public Student SelectedStudent {          get {            return _selectedStudent;          }          set {             _selectedStudent = value;            DeleteCommand.RaiseCanExecuteChanged();          }       }      private void OnDelete() {          Students.Remove(SelectedStudent);       }      private bool CanDelete() {          return SelectedStudent != null;       }   } }

在StudentView.xaml中,我们需要在ListBox中添加SelectedItem属性,它将绑定到SelectStudent属性.

<ListBox ItemsSource = "{Binding Students}" SelectedItem = "{Binding SelectedStudent}"/>

以下是完整的xaml文件.

<UserControl x:Class = "MVVMDemo.Views.StudentView"    xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"    xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"    xmlns:local = "clr-namespace:MVVMDemo.Views"    xmlns:viewModel = "clr-namespace:MVVMDemo.ViewModel"    xmlns:data = "clr-namespace:MVVMDemo.Model"    xmlns:vml = "clr-namespace:MVVMDemo.VML"    vml:ViewModelLocator.AutoHookedUpViewModel = "True"    mc:Ignorable = "d"   d:DesignHeight = "300" d:DesignWidth = "300">   <UserControl.Resources>       <DataTemplate DataType = "{x:Type data:Student}">          <StackPanel Orientation = "Horizontal">             <TextBox Text = "{Binding Path = FirstName, Mode = TwoWay}"                Width = "100" Margin = "3 5 3 5"/>             <TextBox Text = "{Binding Path = LastName, Mode = TwoWay}"                Width = "100" Margin = "0 5 3 5"/>             <TextBlock Text = "{Binding Path = FullName, Mode = OneWay}"                Margin = "0 5 3 5"/>          </StackPanel>       </DataTemplate>    </UserControl.Resources>   <Grid>       <StackPanel Orientation = "Horizontal">          <ListBox ItemsSource = "{Binding Students}"             SelectedItem = "{Binding SelectedStudent}"/>          <Button Content = "Delete"             Command = "{Binding DeleteCommand}"            HorizontalAlignment = "Left"             VerticalAlignment = "Top"             Width = "75" />       </StackPanel>    </Grid></UserControl>

编译并执行上述代码后,您将看到以下窗口.

View和ViewModel Communication MainWindow1

您可以看到删除按钮被禁用.选择任何项目时都会启用它.

View and ViewModel Communication MainWindow2

选择任何项目并按删除.您将看到所选项目列表被删除,删除按钮再次被禁用.

View and ViewModel Communication MainWindow3

我们建议您逐步执行上述示例,以便更好地理解.

免责声明:以上内容(如有图片或视频亦包括在内)有转载其他网站资源,如有侵权请联系删除

咨询热线(9:00 - 18:00)
0755 - 29812418
微信公众号二维码
微信公众号二维码
微信公众号
返回顶部