前阵子有人问我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. create和grant配合使用,对Mysql进行创建用户和对用户授权

    1.首先创建用户username以及密码passwd,授权主机localhost. create user ‘username’@'localhost' identified by 'passwd' ...

  2. VS2008的DLL项目添加了方法但是找不到怎么办?

      VS2008中建立了一个DLL项目,使用了一段时间后,在其中一个类中添加了一个方法,然后编译后,拷贝了新的.h文件到使用DLL的项目中,并且.dll和.lib也拷贝到了需要的位置,但是在目标项目中 ...

  3. C++之jsoncpp学习

    最新由于客户端要用到jsoncpp,所以自己也跟着项目的需求学了一下jsoncpp.以前没用过xml,但是感觉接触json后,还蛮好用的. 参考地址 http://jsoncpp.sourceforg ...

  4. htmL5 html5Validate

    http://www.zhangxinxu.com/wordpress/2012/12/jquery-html5validate-html5-form-validate-plugin/

  5. SQL SERVER连接、合并查询

    ----创建测试表MyStudentInfoCREATE table MyStudentInfo(  Id int not null primary key,  Name varchar(16),  ...

  6. [转载] Android中Xposed框架篇---利用Xposed框架实现拦截系统方法

    本文转载自: http://www.wjdiankong.cn/android%E4%B8%ADxposed%E6%A1%86%E6%9E%B6%E7%AF%87-%E5%88%A9%E7%94%A8 ...

  7. iOS中UITableView数据源刷新了,但tableview当中的cell没有刷新

    你会不会遇到通过断点查看数据源模型的确刷新了,但是tableview没有刷新的情况,我遇到了,并通过下面的方法解决了,供大家参考! 在tableview中的数据源代理方法 p.p1 { margin: ...

  8. MySQL安装常见问题(找不到文件,系统服务无法启动...)

    在安装mysql时总是会遇到问题,每次重新安装都会花很多时间来排查.在网上其实有很多相关的文章,但很多都只讲了方法,但没讲具体细节问题,导致无法解决问题.其实有时候知道问题的原因,但总是因为一些细节问 ...

  9. hdu 1573 X问题 (非互质的中国剩余定理)

    X问题 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  10. Python全栈--9.1--面向对象进阶-super 类对象成员--类属性- 私有属性 查找源码类对象步骤 类特殊成员 isinstance issubclass 异常处理

    上一篇文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中) 对象 ...