在现代软件开发中,用户界面(UI)的设计和实现变得越来越复杂。为了更好地分离关注点、提高代码的可维护性和测试性,许多设计模式应运而生。MVVM(Model-View-ViewModel)是其中一种非常流行的设计模式,特别适用于使用数据绑定技术的应用程序。
什么是 MVVM?
定义
MVVM(Model-View-ViewModel)是一种架构设计模式,用于简化用户界面(UI)的开发。它将应用程序分为三个主要部分:
基本概念
示例场景
假设我们需要开发一个简单的待办事项应用程序,允许用户添加、删除和查看待办事项。我们可以使用 MVVM 模式来实现这个应用程序,从而更好地分离关注点,提高代码的可维护性和测试性。
MVVM 的实现
下面我们将通过一个具体的例子来展示如何在 C# 中实现 MVVM 设计模式。
创建 Model 类
首先,我们定义一个简单的待办事项模型类 TodoItem
,用于表示待办事项的信息。
// TodoItem.cs
public class TodoItem
{
public int Id { get; set; }
public string Title { get; set; }
public bool IsCompleted { get; set; }
public TodoItem(int id, string title, bool isCompleted)
{
Id = id;
Title = title;
IsCompleted = isCompleted;
}
public override string ToString()
{
return $"Id: {Id}, Title: {Title}, IsCompleted: {IsCompleted}";
}
}
创建 ViewModel 类
接下来,我们创建一个 TodoViewModel
类,作为中介,负责将 Model 中的数据转换为 View 可以使用的格式,并处理来自 View 的用户输入。
// TodoViewModel.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class TodoViewModel : INotifyPropertyChanged
{
private ObservableCollection todoItems;
private string newTodoTitle;
public event PropertyChangedEventHandler PropertyChanged;
// 使用属性通知机制,当属性值发生变化时通知视图更新
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public ObservableCollection TodoItems
{
get => todoItems;
set
{
todoItems = value;
OnPropertyChanged();
}
}
public string NewTodoTitle
{
get => newTodoTitle;
set
{
newTodoTitle = value;
OnPropertyChanged();
}
}
public TodoViewModel()
{
TodoItems = new ObservableCollection();
}
// 添加待办事项命令
public void AddTodoItem()
{
if (!string.IsNullOrWhiteSpace(NewTodoTitle))
{
var newItem = new TodoItem(TodoItems.Count + 1, NewTodoTitle, false);
TodoItems.Add(newItem);
NewTodoTitle = string.Empty;
}
}
// 删除待办事项命令
public void RemoveTodoItem(TodoItem item)
{
TodoItems.Remove(item);
}
}
创建 View 类
接下来,我们创建一个简单的 WPF 窗口 MainWindow.xaml
,用于显示待办事项列表,并允许用户添加新的待办事项。
绑定 ViewModel 到 View
在 MainWindow.xaml.cs
中,我们将 TodoViewModel
绑定到 MainWindow
。
// MainWindow.xaml.cs
using System.Windows;
namespace TodoApp
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new TodoViewModel(); // 设置数据上下文为 TodoViewModel 实例
}
}
}
执行结果
运行上述代码后,用户可以看到一个简单的待办事项应用程序窗口。用户可以在文本框中输入新的待办事项标题,并点击“Add Todo”按钮将其添加到列表中。每个待办事项旁边都有一个“Remove”按钮,可以删除对应的待办事项。
MVVM 的高级用法
为了更好地理解 MVVM 的高级用法,我们可以进一步扩展上面的例子,引入更多复杂的场景和功能。
使用 ICommand 接口
在 ViewModel 中,我们可以使用 ICommand
接口来实现命令绑定,使代码更加清晰和易于维护。
// RelayCommand.cs
using System;
using System.Windows.Input;
public class RelayCommand : ICommand
{
private readonly Action
更新 ViewModel 类
我们在 TodoViewModel
中使用 RelayCommand
来实现命令绑定。
// TodoViewModel.cs
public class TodoViewModel : INotifyPropertyChanged
{
private ObservableCollection todoItems;
private string newTodoTitle;
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public ObservableCollection TodoItems
{
get => todoItems;
set
{
todoItems = value;
OnPropertyChanged();
}
}
public string NewTodoTitle
{
get => newTodoTitle;
set
{
newTodoTitle = value;
OnPropertyChanged();
}
}
public ICommand AddTodoCommand { get; }
public ICommand RemoveTodoCommand { get; }
public TodoViewModel()
{
TodoItems = new ObservableCollection();
AddTodoCommand = new RelayCommand(AddTodoItem);
RemoveTodoCommand = new RelayCommand(RemoveTodoItem);
}
public void AddTodoItem(object parameter)
{
if (!string.IsNullOrWhiteSpace(NewTodoTitle))
{
var newItem = new TodoItem(TodoItems.Count + 1, NewTodoTitle, false);
TodoItems.Add(newItem);
NewTodoTitle = string.Empty;
}
}
public void RemoveTodoItem(object parameter)
{
if (parameter is TodoItem item)
{
TodoItems.Remove(item);
}
}
}
更新 View 类
在 MainWindow.xaml
中,我们使用命令绑定来调用 AddTodoCommand
和 RemoveTodoCommand
。
执行结果
运行上述代码后,用户可以看到一个简单的待办事项应用程序窗口。用户可以在文本框中输入新的待办事项标题,并点击“Add Todo”按钮将其添加到列表中。每个待办事项旁边都有一个“Remove”按钮,可以删除对应的待办事项。
MVVM 的优缺点
优点
ICommand
接口,可以将命令绑定到 UI 控件,使代码更加清晰和易于维护。缺点
应用场景
MVVM 在许多实际应用场景中都非常有用,以下是一些常见的应用场景:
总结
MVVM(Model-View-ViewModel)是一种非常强大的设计模式,它能够有效地分离业务逻辑、数据和 UI,提高代码的可维护性和测试性。通过使用 MVVM,开发者可以以一种简洁的方式实现复杂的应用程序,适用于多种类型的应用场景。