前阵子有人问我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. 误将文件push到Git,如何删除

    首先在本地删除多余文件夹(文件) 使用git add -u  git add -u,使用-u参数调用了git add命令,会将本地有改动(包括删除和修改)的已经追踪的文件标记到暂存区中.    再co ...

  2. codeforces 361 E - Mike and Geometry Problem

    原题: Description Mike wants to prepare for IMO but he doesn't know geometry, so his teacher gave him ...

  3. JQuery 简单的文字超出部分隐藏下拉显示

    HTML代码: <body> <div class="txt_bos"><!--在每一个放置文字的class外面包一个div,以便设置动画样式用,同样 ...

  4. uiwebview底部黑边解决

    解决方法 设置webview的opaque为no

  5. machine learning----->什么是机器学习

    1.概述: 学习一门学问的第一步就是要了解这门学问到底是什么,它可以被用来干什么. 本文罗列了学习machine learning的过程中看到的一些写得比较好的文章以及读完这些文章之后对机器学习的初步 ...

  6. cadence学习之——原理图库的添加及器件的放置

    画原理图,库是必不可少的,库有cadence自带的,也可以自己建自己的库,然后在画原理图工程时, 这些库都需要被添加进原理图工程才能使用. 1.库的添加 打开Place Part属性框,操作如下: ( ...

  7. [算法]树上倍增求LCA

    LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...

  8. MapReduce --全排序

    MapReduce全排序的方法1: 每个map任务对自己的输入数据进行排序,但是无法做到全局排序,需要将数据传递到reduce,然后通过reduce进行一次总的排序,但是这样做的要求是只能有一个red ...

  9. HttpURLConnection请求网络数据的Post请求

    //--------全局变量----------- //注册Url    private String urlPath="http://101.200.142.201:8080/VideoP ...

  10. (转)C#中两个问号和一个问号 ??

    小问题难倒很多人.今天发现了这个问题,搜了很长时间才看到记录下. 实例:dt.Columns.Add(firstRow.GetCell(i).StringCellValue ?? string.For ...