MVVM 模式核心架構與實現細節
- 1. MVVM 模式回顧
- 2. ViewModel 的職責與設計
- 2.1 狀態管理
- 2.2 行為暴露
- 3. View 與 ViewModel 的連接
- 3.1 DataContext 的設置
- 3.2 ViewModelLocator 模式
- 4. Model 的角色與實現
- 5. 服務層與依賴注入
- 5.1 服務層抽象
- 5.2 使用依賴注入容器
- 6. 綜合實戰:構建一個完整的 MVVM 應用
- 7. 總結
在前面的章節中,我們已經分別探討了INotifyPropertyChanged和ICommand,它們是 MVVM(Model-View-ViewModel)模式的技術基石。本章將從更高層面整合這些知識,深入解析 MVVM 模式的核心架構思想,並展示如何構建一個結構清晰、可維護、可測試的 WPF 應用程序。
1. MVVM 模式回顧
MVVM 模式旨在將用户界面(View)的開發與業務邏輯和數據(Model)的開發分離,通過一個名為 ViewModel 的中間層來連接它們。
- Model:負責應用程序的數據和業務邏輯。它不關心 UI,純粹是業務領域的抽象。
- View:負責界面的顯示和用户的交互。它通過數據綁定與 ViewModel 交互,不包含任何業務邏輯。
- ViewModel:作為 View 和 Model 之間的橋樑,它負責從 Model 中獲取數據,並將其轉換為 View 可以顯示的格式。同時,它也暴露命令(
ICommand)來響應 View 中的用户交互。
這種分離帶來了諸多好處:
- 可測試性:ViewModel 是純 C#類,可以獨立於 UI 進行單元測試。
- 可維護性:UI 設計和業務邏輯開發可以並行進行,代碼職責清晰。
- 代碼複用:ViewModel 可以在不同的 View 中複用。
2. ViewModel 的職責與設計
ViewModel 是 MVVM 模式的核心,其主要職責是狀態管理和行為暴露。
2.1 狀態管理
ViewModel 負責維護 View 所需的所有狀態,並通過INotifyPropertyChanged通知 View 更新。
ViewModel 狀態示例:
public class UserProfileViewModel : ViewModelBase
{
private string _userName;
public string UserName
{
get => _userName;
set => SetField(ref _userName, value);
}
private bool _isLoading;
public bool IsLoading
{
get => _isLoading;
set => SetField(ref _isLoading, value);
}
}
2.2 行為暴露
ViewModel 通過ICommand接口向 View 暴露行為,而不是事件。
ViewModel 命令示例:
public class UserProfileViewModel : ViewModelBase
{
public ICommand SaveCommand { get; }
public ICommand LoadProfileCommand { get; }
public UserProfileViewModel()
{
SaveCommand = new RelayCommand(ExecuteSave, CanSave);
LoadProfileCommand = new AsyncCommand(ExecuteLoadProfile);
}
private async Task ExecuteLoadProfile()
{
IsLoading = true;
try
{
// 從服務加載數據
var user = await _userService.GetUserAsync(CurrentUserId);
UserName = user.Name;
}
finally
{
IsLoading = false;
}
}
private void ExecuteSave()
{
// 保存邏輯
}
private bool CanSave()
{
return !string.IsNullOrWhiteSpace(UserName) && !IsLoading;
}
}
3. View 與 ViewModel 的連接
View 通過DataContext屬性與 ViewModel 建立連接。
3.1 DataContext 的設置
最直接的方式是在 View 的後台代碼中設置:
public partial class UserProfileView : Window
{
public UserProfileView()
{
InitializeComponent();
this.DataContext = new UserProfileViewModel();
}
}
3.2 ViewModelLocator 模式
在大型應用中,為了更好地解耦和管理 ViewModel 的生命週期,通常採用 ViewModelLocator 模式,並結合依賴注入(DI)容器。
ViewModelLocator 示例:
public class ViewModelLocator
{
public IServiceProvider Services { get; }
public ViewModelLocator()
{
var services = new ServiceCollection();
// 註冊服務
services.AddSingleton<IUserService, MockUserService>();
// 註冊ViewModel
services.AddTransient<UserProfileViewModel>();
Services = services.BuildServiceProvider();
}
public UserProfileViewModel UserProfile => Services.GetRequiredService<UserProfileViewModel>();
}
在App.xaml中聲明 Locator:
<Application.Resources>
<local:ViewModelLocator x:Key="Locator" />
</Application.Resources>
在 View 中設置DataContext:
<Window ...
DataContext="{Binding Source={StaticResource Locator}, Path=UserProfile}">
</Window>
4. Model 的角色與實現
Model 是應用程序的領域模型,通常是簡單的 POCO(Plain Old CLR Object)對象。
Model 示例:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
在某些需要雙向綁定的場景中,Model 也可以實現INotifyPropertyChanged接口。
5. 服務層與依賴注入
為了保持 ViewModel 的純粹性,所有與外部世界的交互(如數據庫訪問、API 調用)都應該抽象到服務層中。
5.1 服務層抽象
public interface IUserService
{
Task<User> GetUserAsync(int userId);
Task SaveUserAsync(User user);
}
public class UserService : IUserService
{
// 實現具體的數據庫或API調用邏輯
}
5.2 使用依賴注入容器
通過構造函數將服務注入到 ViewModel 中,這使得 ViewModel 更易於測試。
public class UserProfileViewModel : ViewModelBase
{
private readonly IUserService _userService;
public UserProfileViewModel(IUserService userService)
{
_userService = userService ?? throw new ArgumentNullException(nameof(userService));
// ...
}
}
6. 綜合實戰:構建一個完整的 MVVM 應用
結合以上概念,一個典型的 WPF MVVM 應用結構如下:
- Views/:存放所有 Window 和 UserControl。
- ViewModels/:存放所有 ViewModel 類。
- Models/:存放領域模型。
- Services/:存放服務接口和實現。
- Infrastructure/ 或 Helpers/:存放
RelayCommand、ViewModelBase等輔助類。 - App.xaml.cs:配置依賴注入容器和 ViewModelLocator。
7. 總結
通過本章學習,我們應該掌握:
- MVVM 模式的核心思想和三大組件的職責。
- 如何設計一個職責清晰的 ViewModel。
- 通過
DataContext和 ViewModelLocator 模式連接 View 和 ViewModel。 - 使用服務層和依賴注入來解耦 ViewModel。
MVVM 模式是構建現代化 WPF 應用的標準。熟練掌握它,將極大地提升開發效率和代碼質量。下一章,我們將探討 WPF 中另一個強大的功能:值轉換器(Value Converters)。