mvvmmvvm入門


備註

本節概述了mvvm是什麼,以及開發人員可能想要使用它的原因。

它還應該提到mvvm中的任何大型主題,並鏈接到相關主題。由於mvvm的文檔是新的,您可能需要創建這些相關主題的初始版本。

C#MVVM摘要和完整示例

摘要:

MVVM是一種體系結構模式,由三個不同的組件( ModelViewViewModel)表示 。為了理解這三個層次,有必要簡要地定義每個層次,然後解釋它們如何協同工作。

模型是驅動業務邏輯的層。它從任何數據源檢索和存儲信息以供ViewModel使用

ViewModel是充當ViewModel之間橋樑的層。它可能會也可能不會將模型中的原始數據轉換為View的可呈現形式。一個示例轉換是:從模型到視圖的“True”或“False”字符串的布爾標誌。

View是表示軟件界面(即GUI)的層。它的作用是顯示 視圖模型給用戶的信息,以及信息的變化傳達 視圖模型

這三個組件通過以下方式相互引用來協同工作:

  • 視圖引用了ViewModel
  • ViewModel引用Model

值得注意的是, ViewViewModel能夠進行雙向通信,稱為數據綁定

雙向通信(數據綁定)的主要成分是INotifyPropertyChanged接口。

通過利用此機制, View可以通過用戶輸入修改ViewModel中的數據, ViewModel可以使用可能已通過模型中的進程或來自存儲庫的更新數據更新的數據更新View

MVVM架構非常強調每個層的關注點分離 。分層使我們受益:

  • 模塊化:每個層的內部實現都可以更改或交換,而不會影響其他層。
  • 提高可測試性:每個層都可以使用偽數據進行單元測試 ,如果ViewModel的代碼是在View的後面編寫的,那麼這是不可能的。

構建:

創建一個新的WPF應用程序項目創建一個新的WPF應用程序項目

在您的解決方案中創建三個新文件夾: ModelViewModelView ,並刪除原始的MainWindow.xaml ,以獲得一個全新的開始。

在解決方案中創建3個新文件夾

創建三個新項目,每個項目對應一個單獨的圖層:

  • 右鍵單擊Model文件夾,然後添加一個名為HelloWorldModel.csClass項。
  • 右鍵單擊ViewModel文件夾,然後添加一個名為HelloWorldViewModel.csClass項。
  • 右鍵單擊View文件夾,然後添加一個名為HelloWorldView.xamlWindow(WPF)項。

添加這三個項目

更改App.xaml 以指向新視圖

<Application x:Class="MyMVVMProject.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:MyMVVMProject"
             StartupUri="/View/HelloWorldView.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>
 

視圖模型:

首先構建ViewModel 。該類必須實現INotifyPropertyChanged 接口,聲明PropertyChangedEventHandler 事件,並創建一個引發事件的方法(源: MSDN:如何實現屬性更改通知 )。接下來,聲明一個字段和相應的屬性,確保在屬性的set 訪問器中調用OnPropertyChanged() 方法。以下示例中的構造函數用於演示ModelViewModel提供數據。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using MyMVVMProject.Model;

namespace MyMVVMProject.ViewModel
{
    // Implements INotifyPropertyChanged interface to support bindings
    public class HelloWorldViewModel : INotifyPropertyChanged
    {
        private string helloString;

        public event PropertyChangedEventHandler PropertyChanged;

        public string HelloString
        {
            get
            {
                return helloString;
            }
            set
            {
                helloString = value;
                OnPropertyChanged();
            }
        }

        /// <summary>
        /// Raises OnPropertychangedEvent when property changes
        /// </summary>
        /// <param name="name">String representing the property name</param>
        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        public HelloWorldViewModel()
        {
            HelloWorldModel helloWorldModel = new HelloWorldModel();
            helloString = helloWorldModel.ImportantInfo;
        }
    }
}
 

模型:

接下來,構建模型 。如前所述, 模型通過從存儲庫中提取數據來提供ViewModel的數據(以及將其推送到存儲庫以進行保存)。下面將使用GetData() 方法對此進行演示,該方法將返回一個簡單的List<string> 。業務邏輯也應用於此層,可以在ConcatenateData() 方法中看到。此方法從先前從我們的“存儲庫”返回的List<string> 構建句子“Hello,world!”。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyMVVMProject.Model
{
    public class HelloWorldModel
    {
        private List<string> repositoryData;
        public string ImportantInfo
        {
            get
            {
                return ConcatenateData(repositoryData);
            }
        }

        public HelloWorldModel()
        {
            repositoryData = GetData();
        }

        /// <summary>
        /// Simulates data retrieval from a repository
        /// </summary>
        /// <returns>List of strings</returns>
        private List<string> GetData()
        {
            repositoryData = new List<string>()
            {
                "Hello",
                "world"
            };
            return repositoryData;
        }

        /// <summary>
        /// Concatenate the information from the list into a fully formed sentence.
        /// </summary>
        /// <returns>A string</returns>
        private string ConcatenateData(List<string> dataList)
        {
            string importantInfo = dataList.ElementAt(0) + ", " + dataList.ElementAt(1) + "!";
            return importantInfo;
        }
    }
}
 

視圖:

最後,可以構建View 。此示例後面的代碼中沒有任何內容需要添加,儘管這可能會因應用程序的需要而有所不同。但是,XAML中添加了幾行。 Window 需要對ViewModel 名稱空間的引用。這將映射到XAML命名空間xmlns:vm="clr-namespace:MyMVVMProject.ViewModel" 。接下來,Window需要一個DataContext 。這設置為<vm:HelloWorldViewModel/> 。現在可以將標籤(或您選擇的控件)添加到窗口中。此階段的關鍵點是確保將Binding設置為您希望顯示為標籤內容的ViewModel的屬性。在這種情況下,它是{Binding HelloString}

綁定到屬性而不是字段很重要,因為在後一種情況下, View不會收到值更改的通知,因為OnPropertyChanged() 方法只會在PropertyChangedEvent 上引發PropertyChangedEvent ,而不是在領域。

<Window x:Class="MyMVVMProject.View.HelloWorldView"
        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:MyMVVMProject.View"
        xmlns:vm="clr-namespace:MyMVVMProject.ViewModel"
        mc:Ignorable="d"
        Title="HelloWorldView" Height="300" Width="300">
    <Window.DataContext>
        <vm:HelloWorldViewModel/>
    </Window.DataContext>
    <Grid>
        <Label x:Name="label" FontSize="30" Content="{Binding HelloString}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>
</Window>