MvvmLight入门教程

简介: MvvmLight是一款应用广泛的MVVM框架

MvvmLight

MvvmLight主要程序库

ViewModelLocator

在.netFramework环境下nuget安装MvvmLight会自动安装依赖项MvvmLightLibs库,如果在.net core环境下需要手动安装MvvmLightLibs库。

.netFramework环境下安装完成后,在ViewModel目录下具有一个ViewModelLocator类,该类的作用是提供依赖注入容器和相关属性。

publicclassViewModelLocator

{

   publicViewModelLocator()

   {

       ServiceLocator.SetLocatorProvider(() =>SimpleIoc.Default);

       //判断是否为设计时

       //if (ViewModelBase.IsInDesignModeStatic)

       SimpleIoc.Default.Register<MainViewModel>();//注册MainViewModel

       SimpleIoc.Default.Register<SubWindowVM>();//注册SubWindowVM

   }

   publicMainViewModelMain

   {

       get

       {   //返回MainViewModel实例,必须在前面进行注册后才可以

           returnServiceLocator.Current.GetInstance<MainViewModel>();

       }

   }

   publicSubWindowVMSubWin

   {

       get

       {

           returnServiceLocator.Current.GetInstance<SubWindowVM>();

       }

   }

   publicstaticvoidCleanup(){}

}

另外,在App.xaml中增加ViewModelLocator资源

<Application.Resources>

   <ResourceDictionary>

       <vm:ViewModelLocator  x:Key="Locator"/>

   </ResourceDictionary>

</Application.Resources>

这样在MainWindow中就可以这样注册DataContext

<WindowDataContext="{Binding Source={StaticResource Locator}, Path=Main}">

ObservableObject

ObservableObject继承了INotifyPropertyChanged,主要是简化了属性改变事件的触发

publicclassMainModel : ObservableObject

{

   privateintmyVar;

   publicintMyProperty

   {

       get { returnmyVar; }

       set

       {

           Set(refmyVar, value);

       }

   }

   privateint_value;

   publicintValue

   {

       get { return_value; }

       set {

           _value=value;

           RaisePropertyChanged("Value");

       }

   }

}

ViewModelBase

ViewModelBase继承了ObservableObjectIcleanup接口,自定义的ViewModel可以自己选择是否要继承ViewModelBase,该类中IsInDesignMode可以用来判断是否属于设计状态中。该类中另一常用的方法是Cleanup虚方法,用于进行资源释放。

资源释放

有时在某个VM中开启一个线程,当关闭View时,对应的VM中的线程仍然不会释放,此时就需要对VM中的线程资源进行释放。

publicclassSubWindowVM : ViewModelBase

{

   boolflag=true;

   privateintmyVar;

   publicintMyProperty

   {

       get { returnmyVar; }

       set { Set(refmyVar, value); }//效果相同

       //set { myVar = value; RaisePropertyChanged(); }

   }

   publicSubWindowVM()

   {

       Task.Run(() =>

       {

           inta=0;

           while (flag)

           {

               Debug.WriteLine($"=========={a++}=========");

               Task.Delay(1000).Wait();

           }

       });

   }

   //需要明确调用

   //释放VM中的资源,如线程,如果不调用,线程无法停止

   //瞬时模式,每次调用后需要清理

   publicoverridevoidCleanup()

   {

       base.Cleanup();

       flag=false;

   }

}

MvvmLight框架不会自动调用Cleanup方法,需要手动调用。比如当窗体关闭的时候,调用Cleanup方法,当时在View中直接调用VM中的方法违反了MVVM原则。不过,可以利用ViewModelLocator中的静态的Cleanup进行统一的资源释放。

ViewModelLocator中定义Cleanup的泛型方法

publicstaticvoidCleanup<T>() whereT:ViewModelBase

{

   ServiceLocator.Current.GetInstance<T>().Cleanup();//释放资源

   SimpleIoc.Default.Unregister<T>();//释放对象

   SimpleIoc.Default.Register<T>();//为下次打开可以用

}

这样在window的Closed事件中,可以直接调用ViewModelLocator中的Cleanup方法

privatevoidWindow_Closed(objectsender, EventArgse)

{

   ViewModelLocator.Cleanup<SubWindowVM>();

}

RelayCommand

RelayCommand继承自ICommand,用法和RouteCommand类似

publicICommandBtnCommand

{

   //get => new RelayCommand(() => { });

   //带参数

   get=>newRelayCommand<string>(obj=>

   { });

   //如果泛型定义为int则会转换失效,这里的泛型一般是引用,不能是值类型,因为用的反射机制

}

//任意事件的处理

publicICommandMouseCommand

{

   get=>newRelayCommand<object>(obj=>

   { });

}

Messenger

常规使用

Messenger使用非常灵活,可以在VM中出发,在View中执行逻辑。

在VM中发送

Messenger.Default.Send<int>(123);//广播方式

在View中注册

Messenger.Default.Register<int>(this,ReceiveMsg1);//广播方式

privatevoidReceiveMsg1(intmsg){}

如果不想以广播的方式进行发送,可以使用指定token的方式

  • 发送Messenger.Default.Send<int>(123, "M1");//指定Token
  • 注册Messenger.Default.Register<int>(this,"M1",ReceiveMsg2);//指定token

现在有如下需求,要在VM中触发,需要打开一个子窗口,并且还要得到子窗口是否打开的返回值。基于MVVM思想,子窗口属于View层,主窗口才能调用。

  • 新建一个类MessageAction

publicclassMessageAction<TValue,MResult>

{

    publicTValuevalue { set; get; }

    publicAction<MResult>State { set; get; }

    publicMessageAction(Action<MResult>state)

    {

        State=state;

    }

}

  • MainWindow

MessageAction<string, bool>ma=newMessageAction<string, bool>(GetReturn);

ma.value="123";

Messenger.Default.Send<MessageAction<string, bool>>(ma);

//可以得到返回值

privatevoidGetReturn(boolb)

{

}

  • MainViewModel

Messenger.Default.Register<MessageAction<string,bool>>(this, ReceiveMsg);

privatevoidReceiveMsg(MessageAction<string,bool>msg)

{

   bools=  newSubWindow().ShowDialog() ==true;//此时需要得到ShowDialog的返回值,true、false

   //使用委托来实现返回值给发送消息者

   stringss=msg.value;

   msg.State.Invoke(s);

   //为什么这样做,因为动作的触发点在VM中,VM中做触发的时候需要进行状态判断,也就是需要有返回值

   //需要View中进行窗口操作,并且返回状态

}

NotificationMessage

发送一个字符串给接受者

//触发

NotificationMessagenm=newNotificationMessage("hello");

Messenger.Default.Send<NotificationMessage>(nm);

//注册

Messenger.Default.Register<NotificationMessage>(this, ReceiveNM);

PropertyChangedMessage

传递一个字符串属性名和值发送给接收者,用于将PropertyChanged事件传播给收件人。

privatestring_value;

publicstringValue

{

   get { return_value; }

   set

   {

       _value=value;

       //有两种方式发送PropertyChangedMessage

       //1.broadcast:true

       Set(ref_value, value,broadcast:true);

       //2.Messenger.Default.Send

       PropertyChangedMessage<string>ddd=newPropertyChangedMessage<string>(Value, _value, "Value");

       Messenger.Default.Send<PropertyChangedMessage<string>>(ddd);

       //3.使用Broadcast

       Broadcast<string>(Value, _value, "Value")

   }

}

DispatcherHelper

//多线程,先检查是否在UI线程,如果不在则把该线程挂上去

//不能直接使用,需要配套

DispatcherHelper.Initialize();//一般把这一句写在App对象中

DispatcherHelper.CheckBeginInvokeOnUI()//异步的

//这样也可以

Application.Current.Dispatcher.Invoke()

相关文章
|
前端开发 C# 设计模式
利刃 MVVMLight 1:MVVMLight介绍以及在项目中的使用
原文:利刃 MVVMLight 1:MVVMLight介绍以及在项目中的使用 一、MVVM 和 MVVMLight介绍 MVVM是Model-View-ViewModel的简写。类似于目前比较流行的MVC、MVP设计模式,主要目的是为了分离视图(View)和模型(Model)的耦合。
1616 0
|
6月前
|
Android开发
windowbuilder如何使用
windowbuilder如何使用
|
测试技术 数据库
PlantUML 入门
PlantUML 入门
446 3
PlantUML 入门
|
存储 前端开发 JavaScript
werkzeug源码阅读-完结篇
Werkzeug是一个全面的WSGI Web应用程序库。它最初是WSGI实用程序各种工具的简单集合,现已成为最高级的WSGI实用程序库之一,是Flask背后的项目。
503 0
werkzeug源码阅读-完结篇
|
C# 容器 开发框架
MEF 插件式开发 - WPF 初体验
原文:MEF 插件式开发 - WPF 初体验 目录 MEF 在 WPF 中的简单应用 加载插件 获取元数据 依赖注入 总结 MEF 在 WPF 中的简单应用 MEF 的开发模式主要适用于插件化的业务场景中,C/S 和 B/S 中都有相应的使用场景,其中包括但不限于 ASP.NET MVC 、ASP WebForms、WPF、UWP 等开发框架。
1167 0