E不小心

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

前阵子有人问我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 

posted on 2014-09-07 22:19  E不小心  阅读(2981)  评论(0编辑  收藏  举报