C#学习--ViewModelLocator的作用

写在前面

又是很久没更新文章了,前几天在和群友们讨论框架的时候,有个人遇到了这样的问题,他说我主程序打开了一个子窗口,对子窗口进行了修改之后,关闭子窗口,当再次打开时子窗口显示的数据是改动之后的数据。当时我看到这个问题,我觉得不可思议,不可能啊,我从来没遇到过这样的情况啊。后来在一个大佬的讲解下我才明白了事情的缘由,如果你也遇到了一样的情况或者刚刚接触MVVM框架,那么请往下看。

传统模式

因为我接触WPF并不是从0开始,我是接手了一个前辈写了一半的程序,所以我在使用MVVM的时候默认就从模仿他的使用思路,这就导致我对MVVM框架中大多基础和细节都半知半解。原来我在创建View和ViewModel并关联他们的时候一直使用的是传统模式。
例如下面这段代码

//MainView.xaml.cs
...
MainViewModel viewmodel;
public MainView()
{
	viewmodel = new MainViewModel();
	this.DataContext = viewmodel;
}
...

这样写,是由View主动创建ViewModel实例,并依赖他。(View依赖ViewModel)
好处是,每次打开这个View时,它对应的ViewModel都是新的,但这也可能成为他的负担,如果有大量的子窗口被重复的打开关闭,那么整个系统的效率就会下降,而且可能会遇到这样的情况,需要某个窗口是单例,也就是说,不管你打开关闭几次,它里面的内容都是时间上连续的。

依赖注入

我用的是Mvvmlighting,在安装的时候会自动生成ViewModel文件夹,和MainViewModel.cs和ViewModelLocator.cs,按照我以前的想法直接不管ViewModelLocator.cs文件,然后在MainWindow.xaml.cs中直接实例化MainViewModel类,做一个数据源绑定。但是这个ViewModelLocator.cs是用来做什么的,下面我们来分析一下他的代码。

//第一部分,注释内容
/*
  In App.xaml:
  <Application.Resources>
      <vm:ViewModelLocator xmlns:vm="clr-namespace:ATTest"
                           x:Key="Locator" />
  </Application.Resources>
  
  In the View:
  DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}"

  You can also use Blend to do all this with the tool's support.
  See http://www.galasoft.ch/mvvm
*/

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;

namespace ATTest.ViewModel
{
    /// <summary>
    /// This class contains static references to all the view models in the
    /// application and provides an entry point for the bindings.
    /// </summary>
    public class ViewModelLocator
    {
    	//第二部分,构造函数
        /// <summary>
        /// Initializes a new instance of the ViewModelLocator class.
        /// </summary>
        public ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

            if (ViewModelBase.IsInDesignModeStatic)
            {
                // Create design time view services and models
                SimpleIoc.Default.Register<IDataService, DesignDataService>();
            }
            else
            {
                // Create run time view services and models
                SimpleIoc.Default.Register<IDataService, DataService>();
            }

            SimpleIoc.Default.Register<MainViewModel>();
        }
		
		//第三部分,我也不知道是啥
        public MainViewModel Main
        {
            get
            {
                return ServiceLocator.Current.GetInstance<MainViewModel>();
            }
        }
        
        public static void Cleanup()
        {
            // TODO Clear the ViewModels
        }
    }
}

我们分三个部分来讲解这个文件。

第一部分

注释部分,很简单的两个信息:
一,它被作为一个全局变量在App.xaml中被定义。
二,告诉你怎么在View中使用它。

第二部分

构造函数部分,也是简单的两句代码
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default) 这句代码创建了一个IOC容器(IOC:控制反转,其实我也不懂,反正就是一个容器,在这个容器里面存储ViewModel中所有类的实例)

SimpleIoc.Default.Register() 这句代码看方法名也知道了,将类注册到这个容器当中,方便容器对他们进行统一管理

第三部分

我也不知道叫啥的部分,就是为了获取容器中对应类的实例。

关联
<Window.DataContext>
	<Binding Path="Main" Source="{StaticResource Locator}"></Binding>
</Window.DataContext>

这样我们就可以依赖注入了,然后绑定对应的控件的依赖项属性。

写在结尾

其实很多同学会问这样写即麻烦又复杂,而且效果也和传统模式一样,为什么还要学呢。首先,不管用不用我们都要了解,万一以后在团队开发中要求使用这样的IOC模式那不是操蛋了,其次,这样绑定有助于了解C#的新特性,将依赖注入都交给容器,而且在一些特定的情况下需要窗口单例模式,就能够使用这样的写法,还有一个特性就是,这样写可以在设计的时候显示你绑定的内容,这就很nice了,不用写完一部分内容,还要编译运行项目才能知道窗口中某些控件绑定的对不对,这就是今天的内容,与君共勉!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值