Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • 6.3 ViewModel的实现

6.3 ViewModel的实现

核心概念

ViewModel是MVVM模式中的关键组件,负责:

  • 封装业务逻辑和状态管理
  • 提供数据绑定所需的属性和命令
  • 保持与View的松耦合关系

基本实现步骤

1. 创建ViewModel基类

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

2. 实现典型ViewModel

public class ProductViewModel : ViewModelBase
{
    private string _productName;
    private decimal _price;

    public string ProductName
    {
        get => _productName;
        set
        {
            _productName = value;
            OnPropertyChanged();
        }
    }

    public decimal Price
    {
        get => _price;
        set
        {
            _price = value;
            OnPropertyChanged();
        }
    }
}

高级实现技巧

依赖注入集成

public class MainViewModel
{
    private readonly IDataService _dataService;

    public MainViewModel(IDataService dataService)
    {
        _dataService = dataService;
    }
}

异步操作处理

public class AsyncViewModel : ViewModelBase
{
    private bool _isLoading;
    private ICommand _loadDataCommand;

    public bool IsLoading
    {
        get => _isLoading;
        set
        {
            _isLoading = value;
            OnPropertyChanged();
        }
    }

    public ICommand LoadDataCommand => _loadDataCommand ??= new AsyncCommand(LoadDataAsync);

    private async Task LoadDataAsync()
    {
        IsLoading = true;
        try {
            // 异步数据加载
        }
        finally {
            IsLoading = false;
        }
    }
}

最佳实践

  1. 关注点分离:

    • 避免在ViewModel中包含UI相关逻辑
    • 将复杂业务逻辑委托给领域服务
  2. 可测试性设计:

    • 保持无状态设计
    • 使用接口依赖而非具体实现
  3. 性能优化:

    • 合理使用延迟加载
    • 避免频繁的属性通知
  4. 错误处理:

    • 实现统一的错误处理机制
    • 提供用户友好的错误信息

常见模式

父子ViewModel通信

public class ParentViewModel
{
    public ChildViewModel Child { get; }

    public ParentViewModel()
    {
        Child = new ChildViewModel();
        Child.PropertyChanged += (s, e) => 
        {
            if(e.PropertyName == nameof(ChildViewModel.IsValid))
            {
                // 响应子ViewModel变化
            }
        };
    }
}

消息总线模式

// 使用Messenger或EventAggregator
messenger.Register<DataUpdatedMessage>(this, message => 
{
    // 处理消息
});

框架集成示例

使用Prism框架

public class PrismViewModel : BindableBase
{
    private string _title;
    private readonly IEventAggregator _eventAggregator;

    public string Title
    {
        get => _title;
        set => SetProperty(ref _title, value);
    }

    public PrismViewModel(IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
    }
}

调试技巧

  1. 输出绑定错误:
<Window ...
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    TextBlock.Text="{Binding Path, diag:PresentationTraceSources.TraceLevel=High}">
  1. 设计时数据:
<Window ...
    d:DataContext="{d:DesignInstance local:DesignTimeViewModel}">
  1. ViewModel状态检查:
  • 使用DebuggerDisplay特性
  • 实现ToString()方法输出关键状态
[DebuggerDisplay("Product: {ProductName} (${Price})")]
public class ProductViewModel : ViewModelBase
{
    public override string ToString() => $"{ProductName} - {Price:C}";
}
Last Updated:: 5/3/25, 10:42 PM