zoukankan      html  css  js  c++  java
  • 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 

    本文原创手打,转载请注明出处。
  • 相关阅读:
    接口性能测试方案
    如何选择自动化测试框架
    一维和二维前缀和
    高精度 加减乘除
    归并排序 快速排序
    链表
    二分查找
    表达式求值
    c++ const问题小记
    虚继承总结
  • 原文地址:https://www.cnblogs.com/gaoshang212/p/3960874.html
Copyright © 2011-2022 走看看