MVVM 概述
MVVM(Model - View - ViewModel)是一种用于构建用户界面的软件设计模式,特别适用于 WPF(Windows Presentation Foundation)、Silverlight、UWP(Universal Windows Platform)等基于 XAML 的技术。该模式旨在将视图(用户界面)和业务逻辑分离,从而提高代码的可维护性、可测试性和可扩展性。
核心组件详解
1. 模型(Model)
- 定义与作用
- 模型代表应用程序的数据和业务逻辑。它是应用程序的核心数据结构和处理规则的集合,负责与数据库、网络服务、文件系统等数据源进行交互,实现数据的存储、检索、更新和删除等操作。模型不依赖于视图和视图模型,它是独立于用户界面的。
- 示例
- 以一个简单的图书管理系统为例,
Book
类可以作为模型,它包含了图书的基本信息,如书名、作者、ISBN 等,同时还可以包含一些与图书数据相关的操作方法,如验证 ISBN 的有效性。
- 以一个简单的图书管理系统为例,
csharp
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
public string ISBN { get; set; }
public Book(string title, string author, string isbn)
{
Title = title;
Author = author;
ISBN = isbn;
}
public bool IsValidISBN()
{
// 简单的 ISBN 验证逻辑
return !string.IsNullOrEmpty(ISBN) && ISBN.Length == 13;
}
}
2. 视图(View)
- 定义与作用
- 视图是用户界面的可视化呈现,负责展示数据和接收用户的输入。在 WPF 中,视图通常由 XAML 文件定义,XAML 是一种声明式的标记语言,用于描述界面的布局、样式和交互元素。视图只关注界面的外观和用户交互,不包含任何业务逻辑。
- 示例
- 以下是一个简单的 WPF 视图示例,用于显示图书信息:
xml
<Window x:Class="BookManagementSystem.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Book Management System" Height="350" Width="525">
<Grid>
<TextBlock Text="{Binding Title}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
<TextBlock Text="{Binding Author}" HorizontalAlignment="Left" Margin="10,30,0,0" VerticalAlignment="Top"/>
<TextBlock Text="{Binding ISBN}" HorizontalAlignment="Left" Margin="10,50,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>
- 在这个示例中,
TextBlock
控件用于显示图书的标题、作者和 ISBN 信息,通过{Binding}
语法将这些控件的Text
属性绑定到视图模型的相应属性上。
3. 视图模型(ViewModel)
- 定义与作用
- 视图模型是视图和模型之间的桥梁,负责处理视图的逻辑和数据绑定。它包含了视图所需的数据和命令,将模型的数据转换为视图可以展示的格式,并处理用户在视图上的操作。视图模型实现了视图和模型之间的解耦,使得视图和模型可以独立开发和测试。
- 示例
- 以下是一个简单的图书管理系统的视图模型示例:
csharp
using System.ComponentModel;
public class BookViewModel : INotifyPropertyChanged
{
private Book _book;
public string Title
{
get { return _book.Title; }
set
{
if (_book.Title != value)
{
_book.Title = value;
OnPropertyChanged(nameof(Title));
}
}
}
public string Author
{
get { return _book.Author; }
set
{
if (_book.Author != value)
{
_book.Author = value;
OnPropertyChanged(nameof(Author));
}
}
}
public string ISBN
{
get { return _book.ISBN; }
set
{
if (_book.ISBN != value)
{
_book.ISBN = value;
OnPropertyChanged(nameof(ISBN));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public BookViewModel(Book book)
{
_book = book;
}
}
- 在这个示例中,
BookViewModel
类实现了INotifyPropertyChanged
接口,用于实现属性更改通知。当视图模型的属性值发生变化时,会触发PropertyChanged
事件,通知视图进行更新。
关键特性详解
1. 数据绑定
- 定义与作用
- 数据绑定是 MVVM 模式的核心特性之一,它允许视图和视图模型之间建立动态的连接,使得视图能够自动反映视图模型中数据的变化,同时也能将用户在视图上的输入传递给视图模型。在 WPF 中,数据绑定可以通过 XAML 中的
{Binding}
语法或代码来实现。
- 数据绑定是 MVVM 模式的核心特性之一,它允许视图和视图模型之间建立动态的连接,使得视图能够自动反映视图模型中数据的变化,同时也能将用户在视图上的输入传递给视图模型。在 WPF 中,数据绑定可以通过 XAML 中的
- 绑定模式
- OneWay:数据从视图模型流向视图,当视图模型的属性值发生变化时,视图会自动更新。这是最常用的绑定模式,适用于只读属性的绑定。
- TwoWay:数据可以在视图和视图模型之间双向流动,当视图模型的属性值发生变化时,视图会更新;当用户在视图上输入数据时,视图模型的属性值也会更新。适用于可编辑的文本框、复选框等控件的绑定。
- OneTime:数据仅在绑定初始化时从视图模型流向视图,之后视图模型的属性值变化不会影响视图。适用于不需要实时更新的静态数据的绑定。
- 示例
- 以下是一个使用
TwoWay
绑定模式的示例,将一个TextBox
控件的Text
属性绑定到视图模型的Title
属性上:
- 以下是一个使用
xml
<TextBox Text="{Binding Title, Mode=TwoWay}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="200"/>
2. 命令模式
- 定义与作用
- 命令模式是 MVVM 模式中处理用户交互的一种方式,它将用户的操作封装成命令对象,使得视图模型能够处理用户在视图上的操作。在 WPF 中,通常使用
ICommand
接口来实现命令。
- 命令模式是 MVVM 模式中处理用户交互的一种方式,它将用户的操作封装成命令对象,使得视图模型能够处理用户在视图上的操作。在 WPF 中,通常使用
- 示例
- 以下是一个简单的命令实现示例:
csharp
using System;
using System.Windows.Input;
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
- 在视图模型中使用该命令:
csharp
public class BookViewModel
{
public ICommand SaveCommand { get; set; }
public BookViewModel()
{
SaveCommand = new RelayCommand(SaveBook);
}
private void SaveBook(object parameter)
{
// 保存图书数据的逻辑
}
}
- 在视图中绑定命令:
xml
<Button Content="Save" Command="{Binding SaveCommand}" HorizontalAlignment="Left" Margin="10,100,0,0" VerticalAlignment="Top"/>
3. 属性更改通知
- 定义与作用
- 在 MVVM 模式中,当视图模型的属性值发生变化时,需要通知视图进行更新。在 WPF 中,通常通过实现
INotifyPropertyChanged
接口来实现属性更改通知。
- 在 MVVM 模式中,当视图模型的属性值发生变化时,需要通知视图进行更新。在 WPF 中,通常通过实现
- 示例
- 在前面的
BookViewModel
示例中,BookViewModel
类实现了INotifyPropertyChanged
接口,当属性值发生变化时,调用OnPropertyChanged
方法触发PropertyChanged
事件,通知视图进行更新。
- 在前面的
优点
- 可维护性:将视图和业务逻辑分离,使得代码结构更加清晰,易于维护和扩展。当需要修改视图或业务逻辑时,只需要修改相应的部分,而不会影响到其他部分。
- 可测试性:视图模型可以独立于视图进行测试,通过模拟数据和命令,可以方便地对视图模型的业务逻辑进行单元测试。
- 可复用性:视图模型可以在不同的视图中复用,提高了代码的复用性。
总结
MVVM 模式通过将视图和业务逻辑分离,利用数据绑定、命令模式和属性更改通知等特性,提高了代码的可维护性、可测试性和可扩展性。在 WPF 开发中,合理运用 MVVM 模式可以帮助开发者构建高效、可维护的应用程序。