0x5 MVVM

[7.1updated]截止到目前,我们看到7.1的更新主要在三个地方

  1. PrismApplication ,并且不再使用Bootstrapper
  2. 更新了unity,现在使用prism.unity作为容易管理
  3. 更新了IModule接口

    下面所有代码片段都更新到7.1,并且不再赘述与6.x的区别

蛤蛤,终于到MVVM了。特别是前面的Module,忒难写,反正大概知道是怎么用就好了,具体怎么个容器,怎么个依赖注入,我也不是很懂,Prism重度依赖容器,哪哪都是,哪哪都是依赖容器注入。

到目前为止,已经知道怎么去设置Region,怎么去关联View,和关联其他Module里的View了。那么接下来就是MVVM啦,★,°:.☆( ̄▽ ̄)/$:.°★ 。

先看Wiki怎么对MVVM定义的:

MVVM(Model–view–viewmodel)是一种软件架构模式。

MVVM有助于将图形用户界面的开发与业务逻辑或后端逻辑(数据模型)的开发分离开来,这是通过置标语言或GUI代码实现的。MVVM的视图模型是一个值转换器,[1] 这意味着视图模型负责从模型中暴露(转换)数据对象,以便轻松管理和呈现对象。在这方面,视图模型比视图做得更多,并且处理大部分视图的显示逻辑。[1] 视图模型可以实现中介者模式,组织对视图所支持的用例集的后端逻辑的访问。

Dior不Dior?首先他不是WPF专有的,现在很多前端框架都实现了MVVM模式,像Vue,Angular。那MVVM这么火,他到底有什么神奇的地方呢?数据双向绑定!数据双向绑定!数据双向绑定!

我最早在找MVVM框架的时候,其实并不在乎什么解耦,前后端分离,可测试啥的,我只是受够了WinForms前台代码中 ShowDetails和SetModel,后来发现MVVM可以实现双向绑定,数据驱动界面显示,就着了迷(❤´艸`❤)。扯远了,我们来看Prism,怎样实现MVVM的。

ViewModel及定位

什么是ViewModel,ViewModel在MVVM中充当了什么角色?

ViewModel是对应的View(数据和行为)的抽象,View只是ViewModel的一个消费者,那么还有其他的消费者吗?当然有了,那就是单元测试(Unit Test),这个后面说。ViewModel为View提供数据上下文(DataContext),简单的说,你View需要展示的东西,都在我这里,你需要跟我绑定,包括数据和命令,不然你就是个静态的。

那怎么为View指定ViewModel呢,通常情况下,我们是为控件指定Datacontext,而Prism为我们提供了更简单方式,约定。

约定的绑定方式
  • Step1 新建一个Wpf项目,新建两个文件夹Views 和 ViewModels,用来存放View和ViewModel,删掉MainWindow.xaml,并在Views新建一个新 MainWindow窗体当我们的Shell。

    app.xaml.cs:
using Prism.Ioc;
using Prism.Unity;
using System.Windows;
using ViewModelLocator.Views; namespace ViewModelLocator
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
} protected override void RegisterTypes(IContainerRegistry containerRegistry)
{ }
}
}
  • Step2 在ViewModels文件夹内新建,一个MainViewModel的类,继承BindableBase,注意,这里是个类(Class)

MainWindowViewModel.cs

using Prism.Mvvm;

namespace ViewModelLocator.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Unity Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
} public MainWindowViewModel()
{ }
}
}
  • Step3 修改MainWindow.xaml,覆盖下面的代码:(当前也可以不覆盖,对比发现,我们这里只多了一点东西)
<Window x:Class="ViewModelLocator.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True" Title="{Binding Title}" Height="350" Width="525">
<Grid>
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
</Grid>
</Window>

Tips:数据绑定Title="{Binding Title}" ,Title是对应ViewModel里的一个公开属性。

运行后发现,窗口的Title正式MainWindowViewModel里Title的值,可是我们并没有为MainWindow指定ViewModel啊,正常的绑定看上去是应该是这样

    <UserControl.DataContext>
<vm:NumberChangeLogViewModel />
</UserControl.DataContext>

或者这样

<vw:NumberView
DockPanel.Dock="Top"
DataContext="{Binding Path=Number, Mode=OneTime}"
/>

蛤蛤,刚开始我也很懵逼,可是我爱学习,在Prism的源码Prism.Mvvm.ViewModelLocationProvider中我发现了这个:

        /// <summary>
/// ViewModelfactory that provides the View instance and ViewModel type as parameters.
/// </summary>
static Func<object, Type, object> _defaultViewModelFactoryWithViewParameter; /// <summary>
/// Default view type to view model type resolver, assumes the view model is in same assembly as the view type, but in the "ViewModels" namespace.
/// </summary>
static Func<Type, Type> _defaultViewTypeToViewModelTypeResolver =
viewType =>
{
var viewName = viewType.FullName;
viewName = viewName.Replace(".Views.", ".ViewModels.");
var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
var suffix = viewName.EndsWith("View") ? "Model" : "ViewModel";
var viewModelName = String.Format(CultureInfo.InvariantCulture, "{0}{1}, {2}", viewName, suffix, viewAssemblyName);
return Type.GetType(viewModelName);
};

是不是豁然开朗?O(∩_∩)O

我们不一样,定制约定

约定就是要来被打破的,有人可能觉得后缀加一个ViewModel实在是LowB,我想改变他,可以不可以?当然阔以啦。

prism为我们提供了一个可重写的ConfigureViewModelLocator的方法来配置ViewModel的定位器,如果你想修改默认的约定为View的名字后面+VM,你可以在app.xaml.cs这样写:

        protected override void ConfigureViewModelLocator()
{
base.ConfigureViewModelLocator(); ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
{
var viewName = viewType.FullName;
var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
var viewModelName = $"{viewName}VM, {viewAssemblyName}";
return Type.GetType(viewModelName);
});
}
我就是我,是颜色不一样的烟火

这世界上不乏个性鲜明的人,你们那些约定和打破的约定还不都是一路货色。我就要不一样的,我想跟谁绑在一起就跟谁绑在一起。好,你跟谁好是你的自由,Prism不能限制你,不然你会投诉它不民主。

从PRISM开始学WPF(五)MVVM(一)ViewModel?的更多相关文章

  1. 从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator?

    原文:从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator? 从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WP ...

  2. 从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator-更新至Prism7.1

    原文:从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator-更新至Prism7.1 事件聚合器EventAggregator [7.1updated]除了app部分,没 ...

  3. 从PRISM开始学WPF,Prism7更新了什么

    当时我在搬运Prism6.3的sample代码的时候,就是因为网上的资料太老旧,万万没想到这给自己挖了一个坑,因为我在做笔记的时候,prism已经在更新7.0了 现在已经是7.2了,(lll¬ω¬), ...

  4. 从PRISM开始学WPF(一)WPF?

    从PRISM开始学WPF(一)WPF?   我最近打算学习WPF ,在寻找MVVM框架的时候发现了PRISM,在此之前还从一些博客上了解了其他的MVVM框架,比如浅谈WPF中的MVVM框架--MVVM ...

  5. 从PRISM开始学WPF(一)WPF-更新至Prism7.1

    原文:从PRISM开始学WPF(一)WPF-更新至Prism7.1 我最近打算学习WPF ,在寻找MVVM框架的时候发现了PRISM,在此之前还从一些博客上了解了其他的MVVM框架,比如浅谈WPF中的 ...

  6. 从PRISM开始学WPF(八)导航Navigation-更新至Prism7.1

    原文:从PRISM开始学WPF(八)导航Navigation-更新至Prism7.1 0x6Navigation [7.1updated] Navigation 在wpf中并没有变化 Basic Na ...

  7. 从PRISM开始学WPF(番外)共享上下文 RegionContext?

    原文:从PRISM开始学WPF(番外)共享上下文 RegionContext? RegionContext共享上下文 There are a lot of scenarios where you mi ...

  8. 从PRISM开始学WPF(八)导航Navigation?

    原文:从PRISM开始学WPF(八)导航Navigation? 0x6Navigation Basic Navigation Prism中的Navigation提供了一种类似导航的功能,他可以根据用户 ...

  9. 从PRISM开始学WPF(二)Prism?

    目录: 从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WPF(三)Prism-Region? 从PRISM开始学WPF(四)Prism-Modu ...

  10. 从PRISM开始学WPF(二)Prism-更新至Prism7.1

    0x1 PRISM? PRISM项目地址:https://github.com/PrismLibrary/Prism 先看下简介: Prism is a framework for building ...

随机推荐

  1. 【BZOJ3282】Tree (Link-Cut Tree)

    [BZOJ3282]Tree (Link-Cut Tree) 题面 BZOJ权限题呀,良心luogu上有 题解 Link-Cut Tree班子提 最近因为NOIP考炸了 学科也炸了 时间显然没有 以后 ...

  2. log4j日志输出性能优化-缓存、异步

     转载 1.log4j已成为大型系统必不可少的一部分,log4j可以很方便的帮助我们在程序的任何位置输出所要打印的信息,便于我们对系统在调试阶段和正式运行阶段对问题分析和定位.由于日志级别的不同,对系 ...

  3. FJUT2017寒假训练二题解

    A题 题意:让你找出唯一的一个四位数,满足对话时的要求. 思路:因为是4位数,可以直接从1000-9999遍历一遍,判断是否有唯一的数能满足所有条件,如果不是唯一的或者没有满足条件的数就输出Not s ...

  4. 微信小程序基于腾讯云对象存储的图片上传

    在使用腾讯云对象存储之前,公司一直使用的是传统的FTP的上传模式,而随着用户量的不断增加,FTP所暴露出来的问题也越来越多,1.传输效率低,上传速度慢.2.时常有上传其他文件来攻击服务器,安全上得不到 ...

  5. Django数据模型——通用字段选项

    字段 一个模型最重要也是唯一必需的部分,是它定义的数据库字段 字段名称限制 1.字段名不能是python保留字,这样会导致python语法错误 2.字段不能包含连续一个以上的下划线,这样会和Djang ...

  6. nginx里的sticky的作用

    1.Sticky工作原理 : Sticky是nginx的一个模块,它是基于cookie的一种nginx的负载均衡解决方案,通过分发和识别cookie,来使同一个客户端的请求落在同一台服务器上,默认标识 ...

  7. 分享Java开发的利器-Lombok

    译注:Lombok是一个很老的项目了,也非常实用,但奇怪的是这么多年来似乎一直不温不火.很多Lombok特性可以参考它的官网介绍哈.兄弟连教育在这里只是简单介绍一下它的基础功能. Lombok是一个旨 ...

  8. elasticsearch基本操作之--java基本操作 api

    /** * 系统环境: vm12 下的centos 7.2 * 当前安装版本: elasticsearch-2.4.0.tar.gz */ 默认进行了elasticsearch安装和ik安装, 超时配 ...

  9. 可视化:svg相关基础

    01.svg的嵌入.html <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  10. 剑指Offer-平衡二叉树

    package Tree; /** * 平衡二叉树 * 输入一棵二叉树,判断该二叉树是否是平衡二叉树. * 平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法), ...