C# 中的 MVC、MVP、MVVM 模式详解

C# 中的 MVC、MVP、MVVM 模式详解 这三种都是分层架构设计模式核心目标是解耦代码、提高可维护性和可测试性在 C# 开发尤其是桌面 / Web 应用中应用广泛。下面从「定义 核心角色 C# 示例 适用场景」逐一讲解。一、MVCModel-View-Controller1. 核心概念Model数据模型业务逻辑、数据实体不依赖任何层。View视图UI 界面展示数据接收用户输入依赖 Model。Controller控制器处理用户请求协调 Model 和 View比如接收 View 的输入调用 Model 处理数据再更新 View。核心流程用户操作 → Controller 接收 → 调用 Model 处理数据 → Controller 传递数据给 View → View 展示。特点View 和 Controller 双向交互Controller 直接控制 View 的更新。2. C# MVC 简单示例ASP.NET MVC 场景// 1. Model数据模型 public class UserModel { public int Id { get; set; } public string Name { get; set; } // 模拟业务逻辑 public UserModel GetUserById(int id) { return new UserModel { Id id, Name 张三 }; } } // 2. Controller控制器ASP.NET MVC 中继承 Controller 基类 public class UserController : Controller { // 处理用户请求比如访问 /User/Detail/1 public ActionResult Detail(int id) { // 调用 Model 获取数据 var userModel new UserModel(); var user userModel.GetUserById(id); // 将数据传递给 View return View(user); } } // 3. View视图Razor 页面 /Views/User/Detail.cshtml model UserModel h1用户详情/h1 pIDModel.Id/p p姓名Model.Name/p3. 适用场景ASP.NET MVCWeb 应用、WinForm 基础场景。适合简单应用开发速度快但 View 和 Controller 耦合度略高。二、MVPModel-View-Presenter1. 核心概念MVC 的改进版核心是解耦 View 和 Model引入 Presenter 作为中间层Model和 MVC 一致数据 / 业务逻辑。View纯展示层不包含任何业务逻辑仅暴露接口给 Presenter 调用比如ShowUser(UserModel)。Presenter主持人持有 View 和 Model 的引用处理所有业务逻辑是核心层View 的输入交给 PresenterPresenter 调用 Model 后通过 View 接口更新界面。核心流程用户操作 → View 通知 Presenter → Presenter 调用 Model → Presenter 通过 View 接口更新 View。特点View 完全被动Presenter 主导View 和 Model 完全解耦可测试性更强。2. C# MVP 简单示例WinForm 场景// 1. Model public class UserModel { public int Id { get; set; } public string Name { get; set; } public UserModel GetUser(int id) { return new UserModel { Id id, Name 李四 }; } } // 2. View 接口解耦 Presenter 和具体 View public interface IUserView { int UserId { get; set; } // 接收用户输入的 ID void ShowUserInfo(string name); // 展示用户名称 } // 3. Presenter public class UserPresenter { private readonly IUserView _view; private readonly UserModel _model; public UserPresenter(IUserView view) { _view view; _model new UserModel(); } // 处理「查询用户」逻辑 public void LoadUser() { var user _model.GetUser(_view.UserId); _view.ShowUserInfo(user.Name); // 通过接口更新 View } } // 4. 具体 ViewWinForm 窗体 public partial class UserForm : Form, IUserView { private readonly UserPresenter _presenter; public UserForm() { InitializeComponent(); _presenter new UserPresenter(this); // 按钮点击事件绑定 btnQuery.Click (s, e) _presenter.LoadUser(); } // 实现 IUserView 接口 public int UserId { get int.Parse(txtId.Text); set txtId.Text value.ToString(); } public void ShowUserInfo(string name) { lblName.Text name; // 更新界面控件 } }3. 适用场景WinForm/WPF 桌面应用早期、对测试性要求较高的中小型应用。缺点Presenter 可能会变得臃肿需手动处理大量 View 接口。三、MVVMModel-View-ViewModel1. 核心概念MVP 的进阶版核心是数据绑定Data Binding消除 Presenter 手动更新 View 的冗余代码Model和前两者一致数据 / 业务逻辑。View视图UI通过数据绑定和 ViewModel 关联无需手动更新支持双向绑定View 输入自动同步到 ViewModelViewModel 数据变化自动更新 View。ViewModel视图模型封装 View 的逻辑和数据实现INotifyPropertyChanged通知 View 数据变化是 View 的「抽象」不依赖具体 View。核心流程用户操作 → View 绑定的 ViewModel 接收数据 → ViewModel 调用 Model → ViewModel 触发属性变更通知 → View 自动更新。特点数据驱动无需手动更新 ViewView 和 ViewModel 解耦可测试性最高。2. C# MVVM 简单示例WPF 场景// 1. 基础类实现属性变更通知MVVM 核心 public class ObservableObject : INotifyPropertyChanged { public event PropertyChangedEventHandler? PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string? propertyName null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } // 2. Model public class UserModel { public int Id { get; set; } public string Name { get; set; } public UserModel GetUser(int id) { return new UserModel { Id id, Name 王五 }; } } // 3. ViewModel public class UserViewModel : ObservableObject { private readonly UserModel _model; private int _userId; private string _userName; // 绑定到 View 的属性用户输入的 ID public int UserId { get _userId; set { _userId value; OnPropertyChanged(); // 通知 View 数据变化 } } // 绑定到 View 的属性展示的用户名 public string UserName { get _userName; set { _userName value; OnPropertyChanged(); // 通知 View 数据变化 } } // 绑定到 View 按钮的命令 public ICommand LoadUserCommand { get; } public UserViewModel() { _model new UserModel(); // 初始化命令RelayCommand 是 WPF 中常用的命令实现 LoadUserCommand new RelayCommand(LoadUser); } private void LoadUser() { var user _model.GetUser(UserId); UserName user.Name; // 自动通知 View 更新 } } // 辅助RelayCommand 实现WPF 命令接口 public class RelayCommand : ICommand { private readonly Action _execute; public event EventHandler? CanExecuteChanged; public RelayCommand(Action execute) _execute execute; public bool CanExecute(object? parameter) true; public void Execute(object? parameter) _execute(); } // 4. ViewWPF XAML数据绑定 Window x:ClassMVVMDemo.UserWindow xmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentation xmlns:xhttp://schemas.microsoft.com/winfx/2006/xaml xmlns:vmclr-namespace:MVVMDemo Title用户查询 Height200 Width300 !-- 设置 DataContext 为 ViewModel -- Window.DataContext vm:UserViewModel / /Window.DataContext StackPanel Margin20 !-- 双向绑定 UserIdView 输入同步到 ViewModel -- TextBox Text{Binding UserId, ModeTwoWay} PlaceholderText输入用户ID/ !-- 绑定命令点击按钮触发 ViewModel 的 LoadUser 方法 -- Button Content查询 Command{Binding LoadUserCommand} Margin0,10/ !-- 绑定 UserNameViewModel 变化自动更新 View -- TextBlock Text{Binding UserName} FontSize16/ /StackPanel /Window3. 适用场景WPF/MAUI/Blazor现代 C# 界面框架、复杂交互的桌面 / 跨平台应用。优点数据驱动代码量少可测试性和可维护性最优缺点学习成本略高需理解数据绑定、命令等概念。四、三者核心对比特性MVCMVPMVVM核心解耦View-Controller 耦合View-Presenter 接口解耦View-ViewModel 数据绑定解耦交互方式Controller 直接更新 ViewPresenter 调用 View 接口数据绑定自动更新测试性中等较高最高适用框架ASP.NET MVCWinForm早期WPF/MAUI/Blazor代码冗余少中手动写接口少数据绑定总结MVC最基础Controller 主导适合简单 Web 应用如 ASP.NET MVC开发快但耦合略高。MVP解耦 View 和 ModelPresenter 手动控制 View适合早期桌面应用测试性优于 MVC。MVVM数据驱动核心依赖数据绑定是现代 C# 界面开发WPF/MAUI的首选解耦和可维护性最优。核心选择原则简单 Web 用 MVC现代桌面 / 跨平台用 MVVMMVP 仅作为过渡或老项目维护场景使用。