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

📅  最后修改于: 2021-01-11 16:20:35             🧑  作者: Mango

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

介绍

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

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

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

MVVM模式

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

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

关系

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

MVVM模式的好处

使用MVVM模式的好处是:

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

视图

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

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

视图模型

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

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

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

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

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

模型

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

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

将视图模型连接到视图

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

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

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

查看第一个构图

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

查看模型第一个组成

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

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

声明式创建视图模型

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

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


    
        
    
    ...  

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

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

以编程方式创建视图模型

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

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

在View的后台代码中以编程方式构造和分配View模型的优点是操作简单。这种方法的缺点是,视图需要向视图模型提供任何必需的依赖关系。

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

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

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

视图模型定位器是一个自定义类,用于管理视图模型的初始化及其与视图的关联。在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 ,封装了表示逻辑和状态,而Model则封装了业务逻辑和数据。