在本章中,我们将学习如何向MVVM应用程序添加交互性以及如何干净地调用逻辑.您还将看到所有这些都是通过维护松散耦合和良好的结构来完成的,这是MVVM模式的核心.要理解这一切,首先让我们了解命令.
通过命令查看/ViewModel通信
命令模式已有详细记录并经常使用几十年的设计模式.在这种模式中有两个主要的角色,即调用者和接收者.
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>
编译并执行上述代码后,您将看到以下窗口.
您可以看到删除按钮被禁用.选择任何项目时都会启用它.
选择任何项目并按删除.您将看到所选项目列表被删除,删除按钮再次被禁用.
我们建议您逐步执行上述示例,以便更好地理解.
免责声明:以上内容(如有图片或视频亦包括在内)有转载其他网站资源,如有侵权请联系删除
-
设计总结|如何更好地表达活动品牌?
-
谈谈“目标思维”的落地
编辑导读:我们在做数据分析之前,一定要搞清楚需求方的目标到底是什么,要根据目标来重新定义业务方提出的问题,这就是目标思维。目标思维有多重要呢?应该如何落地呢...
-
在线教育平台竞品分析:网易云课堂vs腾讯课堂
本文从移动端出发,对当前比较热门的两款在线教育平台软件-网易云课堂和腾讯课堂进行比较和分析,不足之处还请大家多提意见。 市场分析 随着国内互联网技术的发展和移...
-
即学即用|父亲节活动的4种运营策略
-
B端产品经理和体验设计师的工作职责边界梳理
-
豆果美食电商分支用户体验报告及建议
-
数据分析师如何提高工作效率
在我们的日常工作中,提高工作效率是每个岗位都需要实现的,在工作中,面对比较凌乱的事情时,首先我们需要梳理清楚,按重要级进行开展;本文作者分享了关于...
-
2016中国云计算SaaS移动办公平台年度综合报告
-
网易大布局教育事业:网易公开课、网易云课堂和MOOC分析
-
一篇文章搞懂语音交互的来龙去脉