前阵子有人问我MVVM模式下,在View中嵌套View,切换View。想一想还是写下来吧。

主要就是用到 ContentControl 和 DataTemplate,这算是一种 ViewModel First 的思想吧。

其实好多MVVM的框架,也都提供这样的功能。在ContentControl绑定ViewModel,就可以显示 对应的View。比如 Caliburn.Micro(CM框架).

MVVMLight应该是没有提供的,对他我本身不是很熟,以前知道他很轻,看过原码,真心没有多少,最近在RT中用了下,发现它也加入了IOC的东东。

以下代码没用使用任何第三方框架。

using System.Windows.Input;

namespace ContentDemo
{
// ViewModelBase 只是实现了 INotifyPropertyChanged
class MainViewModel : ViewModelBase
{
     // 如果有IOC这块的东西 可以用IOC代替。
private readonly FirstViewModel _firstViewModel = new FirstViewModel();
private readonly SecondViewModel _secondViewModel = new SecondViewModel(); private object _viewModel; /// <summary>
/// 要绑定和切换的ViewModel
/// </summary>
public object ViewModel
{
get { return _viewModel; }
set
{
if (_viewModel == value)
{
return;
} _viewModel = value;
OnPropertyChanged();
}
} // 下面两个 Command只是为了 切换 ViewModel用的。 private ICommand _firstCommand; public ICommand FirstCommand
{
get
{
return _firstCommand = _firstCommand ?? new DelegateCommand(obj =>
{
ViewModel = _firstViewModel;
});
}
} private ICommand _secondCommand; public ICommand SecondCommand
{
get
{
return _secondCommand = _secondCommand ?? new DelegateCommand(obj =>
{
ViewModel = _secondViewModel;
});
}
}
}
}

这个是ViewModel的代码,ViewModel OK啦,我们就来写View了。

<Window x:Class="ContentDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ContentDemo"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MainViewModel x:Key="MainViewModel" />
<DataTemplate DataType="{x:Type local:FirstViewModel}">
<local:FirstView />
</DataTemplate>
<DataTemplate DataType="{x:Type local:SecondViewModel}">
<local:SecondView />
</DataTemplate>
</Window.Resources>
<Grid DataContext="{StaticResource MainViewModel}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ContentControl Grid.ColumnSpan="2" Content="{Binding Path=ViewModel}" />
<Button Grid.Row="1" Grid.Column="0" Content="ViewModel 1" Command="{Binding Path=FirstCommand}"/>
<Button Grid.Row="1" Grid.Column="1" Content="ViewModel 2" Command="{Binding Path=SecondCommand}"/>
</Grid>
</Window>

其实这也没什么,关键的地方就是,ContentControl的Content要绑定ViewModel,这是用来显示和切换ViewModel对应的View的。

在资源中加入DataTempalte,DataType设置成ViewModel的类型,DataTemplate 写上你的View,只样就可以自动匹配的你ViewModel啦。

注:在WinRT中的DataTemplate是没有DataType属性的,SL里有没有,我记不住了。可以用我最下面说的办法来弄。

下在是 二个ViewModel和View的代码,都很简答,就是为了展示一下。

    class FirstViewModel
{
public string Content { get; set; } public FirstViewModel()
{
Content = "第一个ViewModel";
}
} class SecondViewModel
{
public string Content { get; set; } public SecondViewModel()
{
Content = "第二个ViewModel";
}
}
<UserControl x:Class="ContentDemo.FirstView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Border Background="DarkGray">
<TextBlock Text="{Binding Path=Content}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</Grid>
</UserControl>
<UserControl x:Class="ContentDemo.SecondView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Border Background="DarkMagenta">
<TextBlock Text="{Binding Path=Content}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</Grid>
</UserControl>

这样,我们切换MailViewModel中的ViewModel的时候,就会换成不同的UI了,DataTemplate 中内容的DataContext 也会是相应的ViewModel。

写的很不好,我的语文虽然不是体育老师交的,也是数学老教交出来的。

还是直接源码吧:Code

源码是2013写的,打不开的自行修改 项目文件或复制源码到新项目吧。

可能现在有人发现了,这样每一个用到的ViewModel和都至少写上一个DataTemplate,这样很不爽,重复的代码太多啦。

下一步的关键就是 DataTemplateSelector。说到这个,大家可能就会了,下篇再分解吧。嘿嘿

转载请注明出处:http://www.cnblogs.com/gaoshang212/p/3960874.html

ContentControl 与 ViewModel (一)的更多相关文章

  1. ContentControl 与 ViewModel (二)

    上文说到 可以使用DataTemplateSelector. 其实等于是用 DataTemplateSelector + 动态创建DataTemplate来实现. using System; usin ...

  2. [WPF源码分析]ContentControl依赖项属性的双向绑定,two-way binding view's DependencyProperty and ViewModel's variable

    问题:自定义控件的依赖项属性和VIewModel中的变量不能双向绑定 解决思路:对比.net源码 PresentationFramework  /   System.Windows.Controls ...

  3. 从PRISM开始学WPF(五)MVVM(一)ViewModel?

    从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WPF(三)Prism-Region? 从PRISM开始学WPF(四)Prism-Module? ...

  4. MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息

    MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...

  5. MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信

    MVVM模式解析和在WPF中的实现(五) View和ViewModel的通信 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 M ...

  6. 页面与ViewModel(下)

    在上一篇博客中,笔者分享了一些从页面整体的角度对页面与ViewModel的思考.在本文中笔者希望从相对细节的角度分享一些对页面与ViewModel的思考. 比如,当我们在更新View Model中的绑 ...

  7. 页面与ViewModel(上)

    在UWP淘宝与旺信中,笔者主要负责页面与控件的制作,这些工作看似简单,但要想做的全面细致仍然需要深入的思考.本文想分享一些在UWP旺信的制作过程中,笔者在UI页面与控件制作上体会到的一些心得.可能笔者 ...

  8. JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(三):两个Viewmodel搞定增删改查

    前言:之前博主分享过knockoutJS和BootstrapTable的一些基础用法,都是写基础应用,根本谈不上封装,仅仅是避免了html控件的取值和赋值,远远没有将MVVM的精妙展现出来.最近项目打 ...

  9. 轻量级前端MVVM框架avalon - ViewModel

    废话说了大几篇,我们开始来点干货了~ ViewModel的内部机制 在MVVM中,数据是核心.而jQuery则以DOM为核心. 而DOM只是HTML在JS的世界的抽象,是一个很易变的东西.因此如果业务 ...

随机推荐

  1. 『GreenPlum系列』GreenPlum 4节点集群安装(图文教程)

      目标架构如上图   一.硬件评估 cpu主频,核数推荐CPU核数与磁盘数的比例在12:12以上Instance上执行时只能利用一个CPU核资源进行计算,推荐高主频 内存容量 网络带宽重分布操作 R ...

  2. CentOS6 搭建Git仓库

    近期上了Redmine以后,系统集成了Git的联动功能,于是萌生了搭建内网仓库的想法,特此记录一下: 1.安装Git yum -y install git 2.创建用户及密码 useradd git ...

  3. html a tag's href javascript issue

    a标签的href中写js中遇到的问题(ie中有问题,chrome没问题) <a class="free" href="javascript:{$('#suiteTy ...

  4. [笔记]Modelsim系列01:编译Altera库的方法

    意义:一劳永逸,不用每次对那些包含Quartus II生成文件的工程进行功能仿真时,都需要重新编译一堆东西.节约时间成本. 版本:ModelSim SE 6.5d 打开Modelsim软件,默认会打开 ...

  5. asp.net前台绑定时间格式时,定义时间格式

    <%#Eval("news_time","{0:yyyy-MM-dd}") %><%#((DateTime)Eval("news_t ...

  6. Linux内核分析第四周学习总结:扒开系统调用的三层皮(上)

    韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.用户态.内核 ...

  7. Ubuntu-12.04-server 配置修改静态 IP地址

    前几天在装Ubuntu 12.04 Server版系统的服务器时IP地址写错了,导致服务器不能上网,今天重新修改了一下IP地址,这里做一个总结. 1.配置静态IP地址 sudo vi /etc/net ...

  8. 用Python玩转词云

    第一步:引入相关的库包: #coding:utf-8 __author__ = 'Administrator' import jieba #分词包 import numpy #numpy计算包 imp ...

  9. 《CSS3秘籍》(第三版)-读书笔记(3)

    第9章 装饰网站导航 1.  选择要定义样式的链接 大部分浏览器都支持4种基本的链接状态:未访问的链接.已访问的链接.访问者的鼠标正悬停在上方的链接,以及正被单击的链接.CSS提供了与这些状态对应的4 ...

  10. Convert HTML Entities

    function convert(str) { // :) //return str; var HTML_Entities = { '&':'&', '<':'<', '& ...