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>