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?的更多相关文章

  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. 【HDU4622】Reincarnation(后缀自动机)

    [HDU4622]Reincarnation(后缀自动机) 题面 Vjudge 题意:给定一个串,每次询问l~r组成的子串的不同子串个数 题解 看到字符串的大小很小 而询问数太多 所以我们预处理任意的 ...

  2. 【BZOJ4652】【NOI2016】循环之美(莫比乌斯反演,杜教筛)

    [BZOJ4652]循环之美(莫比乌斯反演,杜教筛) 题解 到底在求什么呢... 首先不管他\(K\)进制的问题啦,真是烦死啦 所以,相当于有一个分数\(\frac{i}{j}\) 因为值要不相等 所 ...

  3. angular 按下回车键触发事件

    angularJs  按下回车键触发事件这个功能很简单,但是今天的却让我掉坑很久.... 由于我的页面上有两个不同方法都传$event事件,如search($event)和create($event) ...

  4. OSI模型和TCP/IP协议族(二)

    OSI模型中的各层 物理层 物理层(physical layer)协调通过物理媒体传送比特流时所需要的各种功能.物理层涉及到接口和传输媒体的机械和电器规约.它还定义了这些物理设备即接口为了实现传输必须 ...

  5. MVC4不支持EF6解决方案 && Nuget控制台操作说明

    问题背景:MVC4不支持EF6,所以要把EF6卸载然后安装EF5.只能降低版本EF5+MVC4或者EF6+MVC5; 这时候: Uninstall-Package EntityFramework -F ...

  6. RedissonLock分布式锁源码分析

    最近碰到的一个问题,Java代码中写了一个定时器,分布式部署的时候,多台同时执行的话就会出现重复的数据,为了避免这种情况,之前是通过在配置文件里写上可以执行这段代码的IP,代码中判断如果跟这个IP相等 ...

  7. linux 环境下安装oracle11g方法及安装过程中遇上的问题解决方法

     Oralce安装教程 1.先安装需要的依赖包 找到哪个没有安装,直接yum install XX,直到所有的都安装完成.注意,可能一个包安装了,再次执行检查,还是提示没有安装,那么就不需要管他们了, ...

  8. 设计模式——中介者模式/调停者模式(C++实现)

    #include <iostream> #include <string> using namespace std; class Colleague; class Mediat ...

  9. Java爬取 百度图片Google图片Bing图片

    先看看抓取的结果. 8个Java类: Startup.java - main函数 ImageCrawler.java - Crawler基类 BaiduImageCrawler.java - 百度图片 ...

  10. 冒泡排序及优化(Java实现)

    向大端冒泡 public class BubbleSort { public static <T extends Comparable<? super T>> void sor ...