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定义的:

MVVMModel–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-更新至Prism7.1的更多相关文章

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

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

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

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

  3. 从PRISM开始学WPF(三)Prism-Region-更新至Prism7.1

    [7.1update]在开始前,我们先看下版本7.1中在本实例中的改动. 首先,项目文件中没有了Bootstrapper.cs,在上一篇的末尾,我们说过了,在7.1中,不见推荐使用Bootstrapp ...

  4. 从PRISM开始学WPF(四)Prism-Module-更新至Prism7.1

    0x4Modules Modules是能够独立开发.测试.部署的功能单元,Modules可以被设计成实现特定业务逻辑的模块(如Profile Management),也可以被设计成实现通用基础设施或服 ...

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 【dfs判负环】BZOJ1489: [HNOI2009]最小圈

    Description 找出一个平均边权最小的圈. Solution 经典问题,二分答案判断有无负环. 但数据范围大,普通spfa会超时,于是用dfs判负环(快多了). 思路是dis设为0,枚举每个点 ...

  2. 【dfs+连通分量】Bzoj1123 POI2008 BLO

    Description Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通. Input 输入n&l ...

  3. BZOJ_3307_雨天的尾巴_线段树合并+树上差分

    BZOJ_3307_雨天的尾巴_线段树合并 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后 ...

  4. Raft算法

    http://www.cnblogs.com/mindwind/p/5231986.html

  5. Postman----设置代理抓取手机上的请求

    一般为方便接口测试,我们都会设置代理,抓取手机上的请求来方便测试,具体的操作方法如下. 操作步骤: 一.手机和电脑连接同一网络,查看电脑连接网络的IP,配置手机的代理 1.查看电脑连接的网络与IP地址 ...

  6. 计算机17-3,4作业E

    E.complete number Description 完数是指一个整数的因子和等于这个数本身,例如6=1+2+3,所以6是一个完数. 按照给定数据范围,找出期中所有完数并输出. Input 数据 ...

  7. html select 标签设置默认选中

    方法有两种. 第一种通过<select>的属性来设置选中项,此方法可以在动态语言如php在后台根据需要控制输出结果. 1 2 3 4 5 < select  id =  " ...

  8. javascript正则表达式学习(二)--位置匹配

    文章首发于sau交流学习社区 一.前言 正则表达式是匹配模式,要么是匹配字符,要么匹配位置. 其实在开发中很少用到匹配位置,本篇文章主要包含: 二.什么是位置 位置:相邻字符之间的位置. 三.如何匹配 ...

  9. [Hyperledger] Fabric系统中 peer模块的 gossip服务详解

    最近一直在看fabric系统中的核心模块之一——peer模块.在看peer的配置文件core.yaml的信息时,对其中的gossip配置选项很感兴趣.看了一上午,还是不能明白这个选项到底什么意思呢?表 ...

  10. 从mysql中拿到的数据构造为列表

    最近测试接口遇到一个问题,用python2.7从mysql中取到的数据是元祖类型的,元祖内部的元素也是一个元祖(并且部分元素的编码格式是unicode的): 类似这样: ((10144, u''), ...