首页 > 代码库 > ContentControl 与 ViewModel (一)

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 (一)