程序员

MVVMLight的流程简单分析(二)

2018-01-06  本文已影响0人  浅浅的笑意

时间过得可真快,转眼就2018年了。

2018年的第一篇文章,就继续简单讲一下mvvmlight的整个应用启动的那些部分,为了避免自己忘记。


App启动

APP分部类

首先关注的肯定是APP类启动的地方,我们从app.xaml.cs开始着手。我们看到有好几个函数,因为是讲流程,所以就不每个函数都介绍过去了,这里重点关注那个OnLaunched函数。这个是App一开始启动调用的函数。

从注释也可以看出,这是在用户启动应用是触发调用。

        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
            //TODO: 中文为自己添加的注释说明

            //首先获取当前窗口的内容
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            //如果内容也就是框架Frame为空,则创建一个新的,并放置到窗口中
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                rootFrame.NavigationFailed += OnNavigationFailed;

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            //全新应用启动时,会进入这个if条件中
            if (e.PrelaunchActivated == false)
            {
                //判断框架中是否存在内容,主要是页面Page类
                if (rootFrame.Content == null)
                {
                    // When the navigation stack isn't restored navigate to the first page,
                    // configuring the new page by passing required information as a navigation
                    // parameter
                    //初始时,导航栈肯定为空,我们需要导航到第一页,即放置内容到框架中。
                    //这个页面就是我们的首页,或者说主页面。
                    rootFrame.Navigate(typeof(MainPage), e.Arguments);
                }
                // Ensure the current window is active
                Window.Current.Activate();
            }
            //这里是MVVMLight框架封装的一个调度工具
            //主要的用处是让我们可以在非UI线程中,可以委托调度器帮我们去完成UI的操作
            //在此处初始化
            DispatcherHelper.Initialize();

            //MVVMLight在此处注册了一个消息,
            //我们可以看到上图中的那个函数就是消息的回调
            //自己暂时没用过这个封装的消息工具
            Messenger.Default.Register<NotificationMessageAction<string>>(
                this,
                HandleNotificationMessage);
        }

当然我们知道这个是App的分部类,那么其他的部分在app.xaml文件中。而在那里,声明了很重要的东西。我们接着往下看。

App分部类

这是一个xaml文件,我们不需要理会那些声明的命名空间,即那些奇怪的类似于网址的东西。重点关注其中可以看到应用资源中声明了一个叫做vm:ViewModelLocator的东西。

前缀vm在上面可以看到是引入了命名空间,而且是位于我们的ViewModel文件夹下。

这个Key=Locator的东西不知道怎么称呼,查字典叫做定位器。其实有点类似于公交总中心的意思。而这个资源的声明,对于我们后面的调用极其关键。

我们打开这个ViewModelLocator类文件。它的代码如下所示,我也加上了自己的一些注释,应该可以简单理解。(我也说不很深入...)

    /// <summary>
    /// This class contains static references to all the view models in the
    /// application and provides an entry point for the bindings.
    /// <para>
    /// See http://www.mvvmlight.net
    /// </para>
    /// </summary>
    public class ViewModelLocator
    {
        public const string SecondPageKey = "SecondPage";

        /// <summary>
        /// This property can be used to force the application to run with design time data.
        /// </summary>
        public static bool UseDesignTimeData
        {
            get
            {
                return false;
            }
        }

        static ViewModelLocator()
        {
            //设置一个简单IOC容器,放到ServiceLocator中(类似放东西到ServiceLocator仓库)
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

            //声明一个导航服务,MVVMLight封装的
            var nav = new NavigationService();
            //配置页面到导航服务中
            nav.Configure(SecondPageKey, typeof(SecondPage));
            //在IOC依赖注入容器中注册导航服务
            //一个是接口用来解耦用的,真实实例的是后面的我们配置的导航服务实例
            SimpleIoc.Default.Register<INavigationService>(() => nav);

            //同上,注册了对话框服务,这个也是MVVMLight封装的
            SimpleIoc.Default.Register<IDialogService, DialogService>();

            //上述都是一些常用的服务,我们一般都加上
            //如下是自己定义的数据服务,这个数据接口IDataService可以自己随意定义
            //然后注册入简单IOC容器中
            if (ViewModelBase.IsInDesignModeStatic
                    || UseDesignTimeData)
            {
                SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
            }
            else
            {
                SimpleIoc.Default.Register<IDataService, DataService>();
            }

            //最后,我们注册了页面相关的ViewModel
            SimpleIoc.Default.Register<MainViewModel>();
        }

        /// <summary>
        /// Gets the Main property.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
            "CA1822:MarkMembersAsStatic",
            Justification = "This non-static member is needed for data binding purposes.")]
        //ServiceLocator中的Current属性存放的就是我们的简单IOC容器
        //当我们调用IOC容器的GetInstance方法时,IOC容器会自动组装实例返回给我们。
        //MainViewModel的构造函数不是无参的,而那些依赖的东西,IOC容器都帮我们在初始化时加入了进去。
        public MainViewModel Main => ServiceLocator.Current.GetInstance<MainViewModel>();
    }

今天就写到这里吧,之后还会再写后续的东西。现在想去玩其他的东西了,大家下回见面,2018还很漫长,希望大家今年也有更多的收获~~~
谢谢了!!
下一篇

上一篇下一篇

猜你喜欢

热点阅读