====================================== WPF 进阶:MVVM 与实践 ====================================== MVVM 模式是 WPF 的核心设计模式。 MVVM 模式详解 =============== .. code-block:: ┌─────────────────────────────────────────────────────────┐ │ View(XAML) │ │ 负责 UI 呈现、动画、视觉布局 │ │ 通过 Binding 连接到 ViewModel │ │ × 尽量不包含代码逻辑 │ ├─────────────────────────────────────────────────────────┤ │ ViewModel │ │ 负责 UI 状态和逻辑 │ │ 实现 INotifyPropertyChanged │ │ 暴露属性 + 命令(ICommand) │ │ × 不直接引用 UI 控件 │ ├─────────────────────────────────────────────────────────┤ │ Model │ │ 业务数据 + 领域逻辑 │ │ 数据库/网络/文件访问 │ │ × 不知道 View 和 ViewModel 的存在 │ └─────────────────────────────────────────────────────────┘ 完整 MVVM 示例 ================= Model ------ .. code-block:: csharp public class UserModel { public int Id { get; set; } public string Name { get; set; } = ""; public string Email { get; set; } = ""; public DateTime CreatedAt { get; set; } } ViewModel ---------- .. code-block:: csharp public class UserViewModel : ViewModelBase { private readonly IUserService _userService; private ObservableCollection _users = new(); public ObservableCollection Users { get => _users; set => SetProperty(ref _users, value); } private UserModel? _selectedUser; public UserModel? SelectedUser { get => _selectedUser; set { SetProperty(ref _selectedUser, value); DeleteCommand.RaiseCanExecuteChanged(); } } private bool _isLoading; public bool IsLoading { get => _isLoading; set => SetProperty(ref _isLoading, value); } private string _searchText = ""; public string SearchText { get => _searchText; set { SetProperty(ref _searchText, value); _ = SearchAsync(); // 输入即搜索 } } // 命令 public AsyncRelayCommand LoadCommand { get; } public RelayCommand DeleteCommand { get; } public UserViewModel(IUserService userService) { _userService = userService; LoadCommand = new AsyncRelayCommand(async () => { IsLoading = true; try { var result = await _userService.GetAllAsync(); Users = new ObservableCollection(result); } finally { IsLoading = false; } }); DeleteCommand = new RelayCommand( execute: async _ => { if (SelectedUser == null) return; await _userService.DeleteAsync(SelectedUser.Id); Users.Remove(SelectedUser); }, canExecute: _ => SelectedUser != null); } private async Task SearchAsync() { if (string.IsNullOrWhiteSpace(SearchText)) { await LoadCommand.ExecuteAsync(null); return; } var result = await _userService.SearchAsync(SearchText); Users = new ObservableCollection(result); } } View(XAML) ------------- .. code-block:: xml 转换器 ======== .. code-block:: csharp // 值转换器 [ValueConversion(typeof(bool), typeof(Visibility))] public class BoolToVisibilityConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { bool boolValue = (bool)value; return boolValue ? Visibility.Visible : Visibility.Collapsed; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return (Visibility)value == Visibility.Visible; } } // 注册并使用 // // // //