淺談WPF之MVVM工具包

老码识途呀發表於2024-03-25

在之前的WPF示例中,都會用到一個MVVM框,也是一個比較常的MVVM框架,就是MVVM工具包【CommunityToolkit.Mvvm】,今天專門以一個簡單的小例子,簡述一下MVVM工具包的常見用法,僅供學習分享使用,如有不足之處,還請指正。

淺談WPF之MVVM工具包

什麼是MVVM工具包?

CommunityToolkit.Mvvm 包(又名 MVVM 工具包)是一個現代、快速和模組化的 MVVM 庫。 MVVM工具包是 .NET 社群工具包的一部分,圍繞以下原則生成:

  • 獨立於平臺和執行時 - .NET Standard 2.0、.NET Standard 2.1 和 .NET 6🚀(與 UI 框架無關)
  • 易於選取和使用 - 對應用程式結構或編碼範例(“MVVM”之外)沒有嚴格的要求,也就是可以靈活使用。
  • 按需取用 - 自由選擇要使用的元件。
  • 引用實現 - 精簡且高效,為基類庫中包含的介面提供實現,但缺少直接使用它們所需的具體型別。

MVVM 工具包由 Microsoft 維護和釋出,是 .NET Foundation 的一部分。

安裝MVVM工具包

在Visual Studio 開發工具中,可以透過NuGet包管理器進行安裝。點選專案右鍵,選擇“管理NuGet程式包”,開啟NuGet管理視窗,然後搜尋“CommunityToolkit.Mvvm”,進行安裝即可,目前最新版本為8.2.2 。如下所示:

淺談WPF之MVVM工具包

可觀測物件ObservableObject

可觀測物件ObservableObject,實現了 INotifyPropertyChangedINotifyPropertyChanging 介面,是MVVM工具包實現的可觀測物件的基類。如果某些類中的屬性需要具備變更通知功能,則可能繼承此類,如ViewModel或者Model等。主要分兩個步驟:

1. 模型類繼承ObservableObject,即擁有了基類具有的方法和屬性。

2. 將傳統屬性的set方法中欄位=value,修改為SetProperty(ref 欄位名,value)。

以Student為例,如下所示:

using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DemoMVVM.Models
{
    public class Student:ObservableObject
    {
        private int id;

        public int Id
        {
            get { return id; }
            set {SetProperty(ref id , value); }
        }


        private string name;

        public string Name
        {
            get { return name; }
            set { SetProperty(ref name , value); }
        }

    }
}

命令RelayCommand

RelayCommand是ICommand的實現,可以向ViewModel中的方法公開委託,從而可以包裝標準的方法或者Lamada表示式。如下所示:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DemoMVVM.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace DemoMVVM.ViewModels
{
    public class MainWindowViewModel:ObservableObject
    {
        private Student student;

        public Student Student
        {
            get { return student; }
            set { student = value; }
        }

        public MainWindowViewModel()
        {
            student = new Student();
        }

        private ICommand saveCommand;

        public ICommand SaveCommand=>saveCommand??=new RelayCommand(Save);

        private void Save()
        {
            MessageBox.Show($"需要儲存的資訊為Id={Student.Id},Name={Student.Name}!");
        }
    }
}

控制反轉Ioc

使用MVVM模式進行開發,最重要的目的是為了解耦,其中常見的方式就是透過依賴注入的方式實現控制反轉,進而實現解耦。目前來說,MVVM工具包並未實現此功能,因為已經有專門的API來實現,如:Microsoft.Extensions.DependencyInjection。

首先安裝依賴注入的庫【Microsoft.Extensions.DependencyInjection】,當前最新,透過NuGet包管理器進行安裝,如下所示:

淺談WPF之MVVM工具包

在App啟動程式中,建立IServiceProvider對像,並初始化注入ViewModel,如下所示:

using DemoMVVM.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace DemoMVVM
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public IServiceProvider ServiceProvider { get; private set; }

        public new static App Current => (App)Application.Current;

        public App()
        {
            ServiceProvider=ConfigurationServices();
        }


        private static IServiceProvider ConfigurationServices()
        {
            var services = new ServiceCollection();

            services.AddTransient<MainWindowViewModel>();

            return services.BuildServiceProvider();
        }
    }
}

在檢視類中,進行獲取對應的服務即可,如下所示:

using DemoMVVM.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DemoMVVM
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = App.Current.ServiceProvider.GetService(typeof(MainWindowViewModel));
        }
    }
}

以上就實現了控制反轉,將物件的建立與釋放,交到容器去處理,而不是由檢視去做。

檢視資料繫結

因為檢視的DataContext和ViewModel物件是同一個,所以在UI檢視中,只需要對控制元件進行資料繫結即可,如下所示:

<Window x:Class="DemoMVVM.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DemoMVVM"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="400">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.6*"></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock Text="編號" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="10"></TextBlock>
        <TextBox Text="{Binding Student.Id}" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="130" Height="35" Margin="10" VerticalContentAlignment="Center"></TextBox>
        <TextBlock Text="姓名" Grid.Column="0" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="10"></TextBlock>
        <TextBox Text="{Binding Student.Name}" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="130" Height="35" Margin="10" VerticalContentAlignment="Center"></TextBox>
        <Button Content="儲存" Command="{Binding SaveCommand}"  Grid.Row="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="30" Width="120"></Button>
    </Grid>
</Window>

示例演示

經過上述步驟,就實現了MVVM模式的資料繫結和命令呼叫,如下所示

淺談WPF之MVVM工具包

參考文件

在本例項中,只是簡單介紹了MVVM工具包的使用,如若想具體瞭解更詳細內容,可參考官方文件,

1. MVVM工具包:https://learn.microsoft.com/zh-cn/dotnet/communitytoolkit/mvvm/

2. 依賴注入:https://learn.microsoft.com/zh-cn/dotnet/core/extensions/dependency-injection

以上就是【淺談WPF之MVVM工具包】的全部內容,旨在拋磚引玉,一起學習,共同進步。

相關文章