欢迎光临散文网 会员登陆 & 注册

WPF MVVM模式简介

2023-04-07 10:26 作者:百宝门  | 我要投稿


WPF是Windows Presentation Foundation的缩写,它是一种用于创建桌面应用程序的用户界面框架。WPF支持多种开发模式,其中一种叫做MVVM(Model-View-ViewModel)。

什么是MVVM?

MVVM是一种软件架构模式,它将应用程序分为三个层次:Model(模型),View(视图)和ViewModel(视图模型)。Model表示应用程序的数据和业务逻辑,View表示应用程序的用户界面,ViewModel表示View和Model之间的桥梁,它负责处理View的数据绑定和用户交互。

为什么要使用MVVM?

使用MVVM有以下几个好处:

  • 降低了View和Model之间的耦合度,使得它们可以独立地开发和测试。

  • 提高了代码的可重用性和可维护性,因为ViewModel可以在不同的View之间共享。

  • 简化了单元测试,因为ViewModel不依赖于具体的UI控件。

  • 支持双向数据绑定,使得View可以自动更新Model的变化,反之亦然。

  • 利用了WPF提供的强大特性,如命令、依赖属性、数据注解等。

下图我们可以直观的理解MVVM谁急模式:



View: 使用XAML呈现给用户的界面,负责与用户交互,接收用户输入,把数据展现给用户。

Model: 事物的抽象,开发过程中涉及到的事物都可以抽象为Model,例如姓名、年龄、性别、地址等属性.不包含方法,也不需要实现INotifyPropertyChanged接口.

ViewModel: 负责收集需要绑定的数据和命令,聚合Model对象,通过View类的DataContext属性绑定到View。同时也可以处理一些UI逻辑。

如何实现MVVM?

实现MVVM需要遵循以下几个步骤:

  1. 创建一个Model类,定义应用程序所需的数据和业务逻辑。

  2. 创建一个ViewModel类,继承自INotifyPropertyChanged接口,并实现属性变更通知。在ViewModel中定义与Model相关联的属性,并提供相应的命令来执行用户操作。

  3. 创建一个View类(通常是一个XAML文件),定义应用程序的用户界面。在View中使用数据绑定来连接ViewModel中的属性和命令,并设置相关的样式和行为。

  4. 在App.xaml或其他合适的地方创建一个ViewModel实例,并将其作为View中DataContext属性值。

  5. 示例代码:


  1. // Model class

  2. public class User

  3. {

  4.    public string Name { get; set; }

  5.    public int Age { get; set; }

  6. }

  7. // ViewModel class

  8. using System;

  9. using System.Collections.Generic;

  10. using System.ComponentModel;

  11. using System.Linq;

  12. using System.Text;

  13. using System.Threading.Tasks;

  14. using System.Windows.Input;

  15. using System.Windows;

  16. namespace WpfApp1

  17. {

  18.    public class UserInfoViewModel : INotifyPropertyChanged

  19.    {

  20.        private User user;

  21.        public UserInfoViewModel()

  22.        {

  23.            user = new User();

  24.            SaveCommand = new RelayCommand(Save);

  25.            CancelCommand = new RelayCommand(Cancel);

  26.        }

  27.        public string UserName

  28.        {

  29.            get { return user.Name; }

  30.            set

  31.            {

  32.                user.Name = value;

  33.                OnPropertyChanged("UserName");

  34.            }

  35.        }

  36.        public int UserAge

  37.        {

  38.            get { return user.Age; }

  39.            set

  40.            {

  41.                user.Age = value;

  42.                OnPropertyChanged("UserAge");

  43.            }

  44.        }

  45.        public string UserInfo

  46.        {

  47.            get { return $"Name:{UserName} Age:{UserAge}"; }

  48.        }

  49.        public ICommand SaveCommand { get; private set; }

  50.        public ICommand CancelCommand { get; private set; }

  51.        private void Save(object parameter)

  52.        {

  53.            // Save user data to database or service

  54.            MessageBox.Show("User data saved!");

  55.            OnPropertyChanged("UserInfo");

  56.        }

  57.        private void Cancel(object parameter)

  58.        {

  59.            // Close dialog window without saving data

  60.            var window = parameter as Window;

  61.            if (window != null)

  62.                window.Close();

  63.        }

  64.        public event PropertyChangedEventHandler PropertyChanged;

  65.        protected void OnPropertyChanged(string propertyName)

  66.        {

  67.            if (PropertyChanged != null)

  68.                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

  69.        }

  70.    }

  71. }

  72. //Command class

  73. public class RelayCommand : ICommand

  74. {

  75.    public RelayCommand(Action<object> action)

  76.    {

  77.        DoExecute = action;

  78.    }

  79.    public event EventHandler? CanExecuteChanged;

  80.    public Func<object, bool>? CanExecution { set; get; }

  81.    public Action<object>? DoExecute { set; get; }

  82.    public bool CanExecute(object? parameter)

  83.    {

  84.        if (CanExecution != null)

  85.        {

  86.            CanExecute(parameter);

  87.        }

  88.        return true;

  89.    }

  90.    public void Execute(object? parameter)

  91.    {

  92.        DoExecute!.Invoke(parameter!);

  93.    }

  94. }

  1. // View class (XAML file)

  2. <Window x:Class="WpfApp1.MainWindow"

  3.        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  4.        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  5.        Title="MainWindow" Height="220" Width="300">

  6.    <Grid>

  7.        <Grid.RowDefinitions>

  8.            <RowDefinition Height="Auto"/>

  9.            <RowDefinition Height="Auto"/>

  10.            <RowDefinition Height="Auto"/>

  11.            <RowDefinition Height="*"/>

  12.        </Grid.RowDefinitions>

  13.        <Grid.ColumnDefinitions>

  14.            <ColumnDefinition Width="Auto"/>

  15.            <ColumnDefinition Width="*"/>

  16.        </Grid.ColumnDefinitions>

  17.        <!-- Labels and textboxes for user name and age -->

  18.        <Label Content="Name:" Grid.Row="0" Grid.Column="0" Margin="10"/>

  19.        <TextBox Text="{Binding UserName}" Grid.Row="0" Grid.Column="1" Margin="10"/>

  20.        <Label Content="Age:" Grid.Row="1" Grid.Column="0" Margin="10"/>

  21.        <TextBox Text="{Binding UserAge}" Grid.Row="1" Grid.Column="1" Margin="10"/>

  22.        <Label Content="{Binding UserInfo}" Grid.Row="2" Grid.Column="1" Margin="10"/>

  23.        <!-- Buttons for save and cancel commands -->

  24.        <StackPanel Orientation= "Horizontal" HorizontalAlignment= "Right"

  25.                    Grid.Row= "3" Grid.ColumnSpan= "2">

  26.            <Button Content= "Save" Command="{Binding SaveCommand}"

  27.                    CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,

  28.                  AncestorType={x:Type Window}}}" Margin= "10"/>

  29.            <Button Content= "Cancel" Command="{Binding CancelCommand}"

  30.                    CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,

  31.                  AncestorType={x:Type Window}}}" Margin= "10"/>

  32.        </StackPanel>

  33.    </Grid>

  34. </Window>

  1. // View code-behind file

  2. using System.Windows;

  3. namespace WpfApp1

  4. {

  5.   /// Interaction logic for UserInfoView.xaml

  6.   public partial class MainWindow : Window

  7.   {

  8.      public MainWindow()

  9.      {

  10.         InitializeComponent();

  11.         // Set the ViewModel as the DataContext of the View

  12.         this.DataContext = new UserInfoViewModel();

  13.      }

  14.   }

  15. }


运行结果如下:



代码位置:https://github.com/DXG88/WpfApp1.git

有哪些MVVM框架?

虽然可以手动实现MVVM模式,但是也有许多第三方库提供了更方便和高效地使用MVVM模式。以下是一些常见且流行的MVVM框架:

  • Prism: 一个由微软支持的MVVM框架,提供了一系列服务和特性,如导航、模块化、事件聚合、命令、依赖注入等。

  • MVVM Light: 一个轻量级的MVVM框架,提供了一些基础类和组件,如ViewModelBase, RelayCommand, Messenger等。

  • Caliburn.Micro: 一个基于约定而非配置的MVVM框架,提供了一些高级特性,如屏幕激活/关闭生命周期管理、自动绑定、窗口管理器等。

原文地址:WPF MVVM模式简介 - 百宝门的博客 (baibaomen.com)


WPF MVVM模式简介的评论 (共 条)

分享到微博请遵守国家法律