ContentControl 与 ViewModel (一)
前阵子有人问我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 (一)的更多相关文章
- ContentControl 与 ViewModel (二)
上文说到 可以使用DataTemplateSelector. 其实等于是用 DataTemplateSelector + 动态创建DataTemplate来实现. using System; usin ...
- [WPF源码分析]ContentControl依赖项属性的双向绑定,two-way binding view's DependencyProperty and ViewModel's variable
问题:自定义控件的依赖项属性和VIewModel中的变量不能双向绑定 解决思路:对比.net源码 PresentationFramework / System.Windows.Controls ...
- 从PRISM开始学WPF(五)MVVM(一)ViewModel?
从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WPF(三)Prism-Region? 从PRISM开始学WPF(四)Prism-Module? ...
- MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息
MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...
- MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信
MVVM模式解析和在WPF中的实现(五) View和ViewModel的通信 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 M ...
- 页面与ViewModel(下)
在上一篇博客中,笔者分享了一些从页面整体的角度对页面与ViewModel的思考.在本文中笔者希望从相对细节的角度分享一些对页面与ViewModel的思考. 比如,当我们在更新View Model中的绑 ...
- 页面与ViewModel(上)
在UWP淘宝与旺信中,笔者主要负责页面与控件的制作,这些工作看似简单,但要想做的全面细致仍然需要深入的思考.本文想分享一些在UWP旺信的制作过程中,笔者在UI页面与控件制作上体会到的一些心得.可能笔者 ...
- JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(三):两个Viewmodel搞定增删改查
前言:之前博主分享过knockoutJS和BootstrapTable的一些基础用法,都是写基础应用,根本谈不上封装,仅仅是避免了html控件的取值和赋值,远远没有将MVVM的精妙展现出来.最近项目打 ...
- 轻量级前端MVVM框架avalon - ViewModel
废话说了大几篇,我们开始来点干货了~ ViewModel的内部机制 在MVVM中,数据是核心.而jQuery则以DOM为核心. 而DOM只是HTML在JS的世界的抽象,是一个很易变的东西.因此如果业务 ...
随机推荐
- winform.布局
布局:默认布局:自己拖动进行布局,工具栏里对齐方式 右键,锁定.##随容器拉动变化属性:Anchor:上下左右,固定的设置 panel的排列 1.Dock属性:(顺序填充)Top:靠上,高度不变,左右 ...
- Unable to open file 'TYPES.OBJ'
Unable to open file 'TYPES.OBJ' 有旧的控件HPP文件存在,旧控件的HPP文件里是Types::TPoint: 新的Berlin的是System::Types::TPoi ...
- Redis运维的一些常用的命令总结
最近一直管理部门的一些redis的服务器,所以现在来总结一下redis的一些常用的运维命令: 1.time 显示服务器的时间,时间戳(秒) 微秒数 redis 127.0.0.1:6380> ...
- hive中的桶
hive中有桶的概念,对于每一个表或者分区,可以进一步组织成桶,说白点,就是更细粒度的数据范围.hive采用列值哈希,然后除以桶的个数以求余的方式决定该条记录存放在哪个桶当中.使用桶的好处:1.获得更 ...
- linux进程及进程控制
Linux进程控制 程序是一组可执行的静态指令集,而进程(process)是一个执行中的程序实例.利用分时技术,在Linux操作系统上同时可以运行多个进程.分时技术的基本原理是把CPU的运行时间划 ...
- 由tombstone文件解析jni代码过程
Android开发测试会经常遇到crash. (1)adb shell (2)cd /data/tombstones/ (3)adb pull /data/tombstones/tombston_00 ...
- [python] defaultdict
import collections s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)] # defaul ...
- 错误:Method not found: 'Void System.Web.UI.ScriptResourceDefinition.set_LoadSucce
vs2012开发,再把.net 4.5降成4.0.部署到2003 服务器上就报错了. 在网上查了下,老外说:这个方法.net4.0不支持. 后面发现是发布方式错了,用项目里的发布,不要直接拷贝文件过去 ...
- sql ltrim rtrim
sql中用LTRIM ( ),RTRIM ( ).分别截断首尾空格,返回字符表达式. 例1: DECLARE @string_to_trim varchar(60)SET @string_to_tri ...
- MATLAB - 运算符
1.关系运算符用来比较两个数之间的大小关系,在Matlab中的关系运算符包括: < 小于 <= 小于或等于 > 大于 >= 大于或等于 == ...