Xamarin模型-视图-视图模型模式(MVVM)示例解释

本文概述

介绍

MVVM代表Model-View-ViewModel。 MVVM代表将代码分为与领域相关的数据(模型)和数据表示形式(视图), 最后是程序的逻辑(称为业务逻辑)(视图模型)。 ViewModel的职责是可见性。

Xamarin.Forms开发人员需要在XAML中创建一个用户界面, 然后在用户界面上的操作后面添加代码。随着应用程序的修改以及规模和范围的扩大, 出现了维护问题。这些问题包括UI控件和业务逻辑之间的紧密耦合, 这增加了UI修改的成本, 并且将面临代码的单元测试的困难。

Model-View-ViewModel(MVVM)模式有助于将应用程序的业务和表示逻辑与其用户界面分开。在应用程序逻辑和UI之间保持清晰的隔离有助于解决不同的问题, 并使应用程序更易于测试, 维护和发展。它还可以提高代码重用的机会, 并在我们开发应用程序的各个部分时使开发人员和UI设计师可以轻松地进行协作。

MVVM模式

MVVM包含三个核心组件:模型, 视图和视图模型。每个都有不同的功能。

在这里, 我们将显示三个组件之间的不同关系:

Xamarin模型-视图-视图模型模式

关系

此外, 要了解每个组件的职责, 了解它们如何相互影响也很重要。

在较高级别上, 视图”知道”视图模型, 而视图模型知道该模型, 但是该模型不知道视图模型, 而视图模型也不知道View。因此, 视图模型将视图与模型隔离开, 并允许模型独立于视图进行演化。

MVVM模式的好处

使用MVVM模式的好处是:

  • 如果有一个加密当前业务逻辑的现有模型实现, 则更改它可能很困难或有风险。
  • 在这种情况下, 视图模型充当模型类的适配器, 使我们能够避免对模型代码进行任何重大更改。
  • 开发人员无需使用视图即可创建视觉模型和模型的单元测试。视图模型的单元测试可以利用与视图相同的功能。
  • 如果View是在XAML中实现的, 则无需触摸代码即可重新设计应用程序的UI。因此, 新版本的View应该可以与现有的View模型一起使用。
  • 设计人员和开发人员可以在开发过程中独立并同时处理其组件
  • 设计人员可以专注于可视化, 而开发人员可以处理可视化模型和模型组件。

视图

视图负责定义结构的布局和屏幕的外观。每个视图都是在XAML中定义的;它包含有限的代码, 其中不包含业务逻辑。在某些情况下, 隐藏代码可能会提供UI逻辑, 以实现视觉行为, 这在XAML中很难表达, 例如动画。

在Xamarin.Forms应用程序中, “视图”是Page类型或ContentView派生的类。视图也可以由数据模板表示, 该模板指定用于在显示对象时可视化该对象的UI元素。数据模板作为一个视图, 没有任何代码后置, 并且被设计为绑定到特定的视图模型类型。存在用于在视图模型上执行代码以与视图交互的多个选项, 例如单击按钮或选择项目。如果控件支持命令, 则可以将控件的命令数据绑定到视图模型上的Icommand属性。当调用控件的命令时, 将执行视图模型中的代码。除命令外, 行为还可以附加到视图中的对象, 并可以侦听要调用的命令或引发的事件。然后, 在该响应中, 行为可以在视图模型上调用Icommand或在视图模型上调用方法。

视图模型

视图模型实现视图可以绑定数据的属性和命令, 并通过更改通知事件通知视图任何要更改的状态。视图模型的命令和属性定义了UI的功能, 但是View决定了如何显示功能。

View Model还负责协调View与所需的任何模型类的交互。视图模型可能选择直接将模型类公开给视图, 以便视图中的控件可以将数据直接绑定到它们。在这种情况下, 需要设计模型类以支持数据绑定和更改通知事件。每个视图模型都以易于使用的形式提供数据。视图模型有时会执行数据转换。将转换放入视图模型是一个好主意, 因为它提供了View可以绑定到的属性。例如, 视图模型可以合并两个属性的值, 以使其更易于由视图显示。

为了使视图模型参与与视图的双向数据绑定, 其属性必须引发PropertyChanged事件。

视图模型通过实现INotifyPropertyChanged接口并在属性更改时扩展PropertyChanged事件来满足此要求。

对于集合, 提供了对视图友好的ObjervableCollection <T>。此集合实现集合更改通知, 从而使开发人员不必在集合上实现INotifyCollectionChanged接口。

模型

模型类是封装应用程序数据的非可视类。因此, 可以将模型视为代表应用程序的域模型, 该模型通常包括数据模型以及业务和验证逻辑。

模型对象的示例包括数据传输对象(DTO), 普通旧CLR对象(PO​​CO), 以及生成的实体和代理对象。模型类通常与服务或存储库结合使用, 后者封装了数据访问和缓存。

将视图模型连接到视图

可以使用Xamarin.Forms的数据绑定功能将视图模型链接到视图。

可以使用几种方法来构造视图和视图模型, 并在运行时添加它们。

这些方法分为两类, 称为视图优先组合和视图模型优先组合。在”视图优先”构图和”视图模型优先”构图之间选择偏好和复杂性的问题。但是, 所有方法都具有相同的目标, 即将View的视图模型分配给BindingContext属性。

查看第一个构图

这种方法的好处是, 由于视图模型不依赖于视图本身, 因此可以轻松构建松耦合的, 可单元测试的应用程序。通过遵循应用程序的外观结构, 而不是跟踪代码的执行过程来了解类的创建和关联方式, 很容易理解应用程序的结构。而且, Viewfirst结构与Xamarin保持一致。表单导航系统负责在导航发生时构造页面, 这使得视图模型首先组成复杂并且与平台不对齐。

查看模型第一个成分

视图模型优先构图对于某些开发人员而言更为自然。由于视图创建可以被抽象化, 并允许他们专注于应用程序的逻辑非UI结构。而且, 它可以使视图模型可以由其他视图模型创建。但是, 这种方法通常很复杂, 可能很难理解应用程序的各个部分是如何创建和关联的。

这是将视图模型连接到视图的方法。

声明式创建视图模型

View的最直接方法是在XAML中以声明方式初始化其相应的视图模型。构造视图时, 还将构造相应的视图模型对象。

我们将通过以下代码讨论这种方法:

<ContentPage ...xmlns:local="clr-namespace:eShop">
    <ContentPage.BindingContext>
        <local:LoginViewModel />
    </ContentPage.BindingContext>
    ...  
</ContentPage>

创建ContentPage时, 将自动构造LoginViewModel的实例并将其设置为视图的BindingContext。

这样做的好处是它很简单, 但是它的缺点是需要在视图模型中使用默认构造函数。

以编程方式创建视图模型

视图可以在代码隐藏文件中包含代码, 从而导致将视图模型分配给其BindingContext属性。这通常在View的构造函数中完成, 如以下代码所示:

public LoginView()  
{  
    InitializeComponent();  
    BindingContext = new LoginViewModel(navigation service);  
}

视图代码背后的视图模型的编程构造和分配具有简单的优点。这种方法的缺点是, 视图需要为视图模型提供任何必需的依赖关系。

创建定义为数据模板的视图

可以将视图定义为数据模板, 并将其与视图模型类型相关联。数据模板可以定义为资源, 也可以在控件中内联定义, 以显示视图模型。控件的内容是视图模型实例, 并且数据模板用于直观地表示它。此技术是一种情况的示例, 其中视图模型首先初始化, 然后创建视图。

使用视图模型定位器自动创建视图模型

视图模型定位器是一个自定义类, 用于管理视图模型的初始化及其与视图的关联。在EShopOnContainers移动应用程序中, ViewModelLocator类具有附加属性AutoWireViewModel, 该属性用于将视图连接到视图模型。在视图的XAML中, 此附加属性设置为true, 以指示视图模型应自动连接到以下代码所示的视图:

viewModelBase:ViewModelLocator.AutoWireViewModel="true"

AutoWireViewModel属性是一个可绑定属性, 其初始化为false, 并且当值更改时, 将调用OnAutoWireViewModelChanged事件处理程序。此方法解析视图的视图模型。

例:

private static void OnAutoWireViewModelChanged(BindableObject bindable, object oldValue, object newValue)  
{  
    var view = bindable as Element;  
    if (view == null)  
    {  
        return;  
    }  

    var viewType = view.GetType();  
    var viewName = viewType.FullName.Replace(".Views.", ".ViewModels.");  
    var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;  
    var viewModelName = string.Format(  
        CultureInfo.InvariantCulture, "{0}Model, {1}", viewName, viewAssemblyName);  

    var viewModelType = Type.GetType(viewModelName);  
    if (viewModelType == null)  
    {  
        return;  
    }  
    var viewModel = _container.Resolve(viewModelType);  
    view.BindingContext = viewModel;  
}

OnAutoWireViewModelChanged方法尝试使用基于约定的方法来解析视图模型。该约定假定:

  • 视图模型与视图类型在同一装配中。
  • 视图位于-views子命名空间中。
  • 视图模型位于-Viewmodels子命名空间中。
  • 视图模型名称与视图名称相对应, 并以” ViewModel”结尾。

最后, OnAutoWireViewModelChanged方法将视图类型的BindingContext设置为解析的视图模型类型, 以确定有关视图模型类型的更多信息。这种方法的优势在于, 应用程序具有单个类, 该类负责视图模型的初始化及其与视图的连接。

总结

Model-View-ViewModel(MVVM)模式有助于将应用程序的业务和表示逻辑与其用户界面(UI)分开。在应用程序逻辑和UI之间保持清晰的隔离, 这有助于解决众多开发问题, 并使应用程序更易于测试, 维护和发展。它还可以提高代码重用的机会, 并允许开发人员和UI设计师在我们开发应用程序的各个部分时轻松地进行协作。

通过使用MVVM模式, 应用程序的UI, 基础表示和业务逻辑分为三类。类是View, 它封装了表示逻辑和状态, 而模型则封装了业务逻辑和数据。


微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?