MvvmLight框架使用入门(三)

  本篇是MvvmLight框架使用入门的第三篇。从本篇开始,所有代码将通过Windows 10的Universal App来演示。我们将创建一个Universal App并应用MvvmLight框架。

  首先通过VS2015创建一个名为UniversalApp的空工程(工程类型为Universal Windows),然后通过NuGet获取MvvmLight,这里需要注意的是,我们选择MvvmLightLib仅下载DLL文件,因为MvvmLight还未对Universal App做适配,并不会自动创建ViewModel以及ViewModelLocator等文件。

  在创建UniversalApp完成后,将上一篇创建的HelloMvvmLight工程中的ViewModel文件夹整个拷贝到UWP工程里(注意修改namespace)。这样MainViewModel以及ViewModelLocator文件就有了。

接着在App.xaml的Resources中添加对ViewModelLocator的引用:

    <Application.Resources>
        <ResourceDictionary>
            <vm:ViewModelLocator x:Key="Locator" />
        </ResourceDictionary>
    </Application.Resources>

  这里需要注意保持namespace和ViewModel的namespace一致:xmlns:vm="using:UniversalApp.ViewModel"

  再下一步就是修改MainPage.xaml文件,将xaml的内容修改如下:

    <Page.DataContext>
        <Binding Path="Main" Source="{StaticResource Locator}"></Binding>
    </Page.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock Text="{Binding Title}"></TextBlock>
        <Button Grid.Row="1" Command="{Binding ChangeTitleCommand}">Click Me!</Button>
    </Grid>

  至此,一个简单的使用了MvvmLight框架的Uinversal App就完成了。

  按下Ctrl+F5,一个Win10风格的窗体就出现了。(细心的童鞋会发现Button默认不再撑开了)

  当然本篇不会只有这点东西,我们会进一步介绍MvvmLight框架在Universal App下的使用。

  接下来我们增加第二个页面,来看一下MvvmLight对页面间导航的支持。

  第一步新建PageTwoViewModel类:

    public class PageTwoViewModel
    {
        private INavigationService _navigationService;

        public ICommand GoBackCommand { get; set; }

        public PageTwoViewModel(INavigationService navigationService)
        {
            _navigationService = navigationService;
            GoBackCommand = new RelayCommand(()=> { _navigationService.GoBack(); });
        }
    }

  INavigationService是MvvmLight为了抽象各类型的工程(WPF,Silverlight,Windows Runtime)不同的导航方法,而设计的接口,定义如下:

    public interface INavigationService
    {
        string CurrentPageKey { get; }

        void GoBack();

        void NavigateTo(string pageKey);

        void NavigateTo(string pageKey, object parameter);
    }

  通过string字符串确认唯一页面来进行跳转和返回,并可以传递object类型的参数。

  ViewModelLocator类注册PageTwoViewModel,以及创建INavigationService的实例并关联各Page。

        public ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
            SimpleIoc.Default.Register<MainViewModel>();
            SimpleIoc.Default.Register<PageTwoViewModel>();

            var navigationService = this.CreateNavigationService();
            SimpleIoc.Default.Register<INavigationService>(() => navigationService);
        }

        private INavigationService CreateNavigationService()
        {
            var navigationService = new NavigationService();
            navigationService.Configure("MainPage", typeof(MainPage));
            navigationService.Configure("PageTwo", typeof(PageTwo));

            return navigationService;
        }

        public MainViewModel Main
        {
            get
            {
                return ServiceLocator.Current.GetInstance<MainViewModel>();
            }
        }

        public PageTwoViewModel PageTwo
        {
            get
            {
                return ServiceLocator.Current.GetInstance<PageTwoViewModel>();
            }
        }
    }

  至于为什么只要在PageTwoViewModel的构造函数参数中带有INavigationService,即可由IOC自动获取实例navigationService则超出了本文讨论的范围,有兴趣的同学自行学习。

  构建PageTwo.xaml页面并关联至PageTwoViewModel。

    <Page.DataContext>
        <Binding Path="PageTwo" Source="{StaticResource Locator}"></Binding>
    </Page.DataContext>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
            </Grid.RowDefinitions>
            <TextBlock Text="Page Two"></TextBlock>
            <Button Grid.Row="1" Command="{Binding GoBackCommand}">Go Back</Button>
        </Grid>
    </Grid>

  修改MainViewModel类,增加GotoNextCommand等方法。同时我们可以看到手动获取navigationService对象的方法。

    public class MainViewModel : ViewModelBase
    {
        private string title;

        public string Title
        {
            get { return title; }
            set { Set(ref title , value); }
        }

        public ICommand ChangeTitleCommand { get; set; }

        public ICommand GotoNextCommand { get; set; }

        public MainViewModel()
        {
            Title = "Hello World";
            ChangeTitleCommand = new RelayCommand(ChangeTitle);
            GotoNextCommand = new RelayCommand(GotoNext);
        }

        private void GotoNext()
        {
            var navigationService = ServiceLocator.Current.GetInstance<INavigationService>();
            navigationService.NavigateTo("PageTwo");
        }

        private void ChangeTitle()
        {
            Title = "Hello MvvmLight";
        }
    }

  MainPage.xaml仅仅是增加了一个GotoNext的Button:

<Button Grid.Row="2" Command="{Binding GotoNextCommand}">Go to Next!</Button>

  大功告成,按下Ctrl+F5试试吧。

  使用MvvmLight框架中的INavigationService来进行页面导航,虽然相对使用Frame导航稍稍增加了工作量,但具有以下几点好处:

  1.   不依赖具体的工程实现(WPF,Sliverlight,Windows Runtime)。
  2.   View和ViewModel不直接产生依赖,双方通过中介INavigationService打交道。也就是说ViewModel中不会出现Windows.UI.Xaml.Controls的namespace。
  3.   将跳转的实现代码从View转移到ViewModel,使得单元测试可以脱离View,完全的通过ViewModel的UT即可测试跳转的逻辑。
时间: 2024-10-17 19:38:56

MvvmLight框架使用入门(三)的相关文章

MvvmLight框架使用入门(四)

本篇我们着重介绍ViewModelBase,演示Set和RaisePropertyChanged方法的使用,以及就Cleanup方法释放资源展开讨论. ICleanup 接口.实现该接口的ViewModel需要在Cleanup方法里释放资源,特别是-= event ObservableObject 该类实现了INotifyPropertyChanged接口,定义了一个可通知的对象基类,供ViewModelBase继承 ViewModelBase 继承自ObservableObject,   IC

MvvmLight框架使用入门(二)

上一篇我们简单对MvvmLight做了介绍.罗列了三个DLL中,各个命名空间下主要类的定义及大致作用.因为只是范范的概论,对于从未接触过MvvmLight的萌新来说,根本就是在晃点他们.不过万事开头难么,本篇则会以Hello World般的简单例子,来给萌新们当头一击,教会他们使用MvvmLight最最基础的部分. 首先还是动手练习,打开免费又强大的Visual Studio 2015 Community,创建一个WPF Application.不创建Win10的Universal App是因为

实体框架 (EF) 入门 =&gt; 三、CodeFirst 支持的完整特性列表

KeyAttribute 设置主键.如果为int类型,将自动设置为自增长列. 系统默认以Id或类名+Id作为主键.StringLengthAttribute 可设置最大最小长度以及验证提示信息等.最大长度会映射到数据库.MaxLengthAttribute 最大长度.会映射的数据库.ConcurrencyCheckAttribute 修改或删除时,将带此属性的列的原有值与主键一起传送到数据库,如果传递的值与数据库中不一致,则修改或删除失败.用于并发检查.RequiredAttribute 必填字

Thinkphp入门三—框架模板、变量(47)

原文:Thinkphp入门三-框架模板.变量(47) [在控制器调用模板] display()   调用当前操作名称的模板 display(‘名字’)  调用指定名字的模板文件 控制器调用模板四种方式: [在控制器给模板传递变量] 在smarty里边给模板传递变量信息 $smarty -> assign(变量名称,值); 在tp框架里边同样适用assign()给模板传递变量信息 ThinkPHP的模板引擎的左右标记: ThinkPHP/Lib/ Behavior/ ParseTemplateBe

【原创】NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战

前言 本文将演示一个iOS客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo.服务端将分别用MINA2和Netty4进行实现,而通信时服务端你只需选其一就行了.同时用MINA2和Netty4分别实现服务端的目的,是因为很多人都在纠结到底是用MINA还是Netty来实现高并发的Java网络通信服务端,在此干脆两个都实现了,就看你怎么选择了,够吊吧. NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能.这其中最流行的无非就是MINA和Netty了,M

Flex入门(三)——微架构之Cairngorm

大家都知道我们在开发后台的时候,都会使用MVC,三层等分层架构,使后台代码达到职责更为分明单一,高内聚低耦合,例如,Dao层只是进行和数据库打交道,负责处理数据:Service(B层)只是进行逻辑判断处理,而Action则进行后台和前台页面的交互等.从而使程序更加容易管理,更加灵活,更加容易扩展,更加容易维护.也就是大家比较熟悉的Struts(SpringMVC)+Spring+Hibernate(Mybatis)等. 而作为前台Flex处理,也提供了类似的处理功能,想要达到的效果,也是代码分层

迷你MVVM框架 avalonjs 入门教程(司徒正美)

迷你MVVM框架 avalonjs 入门教程 关于AvalonJs 开始的例子 扫描 视图模型 数据模型 绑定属性与动态模板 作用域绑定(ms-controller, ms-important) 模板绑定(ms-include) 数据填充(ms-text, ms-html) 类名切换(ms-class, ms-hover, ms-active) 事件绑定(ms-on,……) 显示绑定(ms-visible) 插入绑定(ms-if) 双工绑定(ms-duplex) 样式绑定(ms-css) 数据绑

OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据

OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据 我们这片博文就来聊聊这个反响很不错的OkHttp了,标题是我恶搞的,本篇将着重详细的分析,探索OkHttp这个框架的使用和封装 一.追其原理 Android系统提供了两种HTTP通信类 HttpURLConnection HttpClient Google推荐使用HttpURLConnection,这个没必要多说,事实上,我这篇写的应该算是比较晚了,很多优秀的博文都已经提出了这些观

AppleWatch开发入门三——代码交互与控制器生命周期

AppleWatch开发入门三--代码交互与控制器生命周期 一.引言 在前两篇博客中,讨论了关于watch开发中框架与界面布局相关,然而主要的逻辑,终究还是要通过代码来实现的,在我们创建了项目之后,就会生成InterfaceController这个文件,它就是我们storyBoard中的入口视图控制器. 二.代码交互与控制器声明周期 storyBoard中的控件我们可以通过拖拽的方式关联到文件中,Action和Outlet两种关联方式基本可以达到我们修改控件和处理业务逻辑的需求. WKInter