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()

相关文章
|
计算机视觉 Python
最快速度写出一个识别效果——OpenCV模板匹配(含代码)
最快速度写出一个识别效果——OpenCV模板匹配(含代码)
1399 0
|
C#
WPF技术之Window.Resources
Window.Resources是在WPF中用于声明和定义资源的机制。通过将资源放置在Window.Resources中,我们可以在窗口内的任何位置引用这些资源,从而实现资源的共享和重用。
1243 0
|
开发框架 .NET API
C#/.NET/.NET Core推荐学习书籍(24年8月更新)
C#/.NET/.NET Core推荐学习书籍(24年8月更新)
508 0
|
监控 安全 测试技术
现在公司都在用的CI/CD框架到底是什么?
现在公司都在用的CI/CD框架到底是什么?
6536 1
WK
|
数据可视化 开发者 容器
QWidget类
QWidget 是 Qt 框架中的基础类,用于创建用户界面的可视化组件。它是所有 UI 组件的基类,提供绘制、布局、事件处理、样式设置和部件通信等功能。常见子类包括 QMainWindow、QDialog、QPushButton 等,支持灵活的窗口管理和丰富的用户交互。
WK
409 3
|
SQL 关系型数据库 数据库连接
Entity Framework Core 入门教程来袭!快速上手强大的 ORM 工具,开启高效数据库开发之旅!
【8月更文挑战第31天】Entity Framework Core(EF Core)是一个轻量且可扩展的对象关系映射(ORM)框架,允许开发者使用 .NET 语言操作数据库而无需直接编写 SQL 语句。本教程涵盖 EF Core 的安装、数据库上下文创建、数据库连接配置及常见数据库操作(如添加、查询、更新和删除),并介绍如何利用数据库迁移功能安全地更改数据库结构。通过本教程,你可以快速掌握 EF Core 的基本用法,提高开发效率。
2088 0
|
虚拟化
VMware Workstation产品常用的快捷键
文章介绍了VMware Workstation产品中常用的快捷键及其功能,包括对虚拟机的控制、设置、快照管理等操作,同时提供了作者的联系方式和博客链接。
1122 15
|
C# Windows
WPF中值转换器的使用
WPF中值转换器的使用
401 1
|
测试技术 持续交付 开发工具
一文掌握:Gitlab的完整使用手册
一文掌握:Gitlab的完整使用手册
|
XML 人工智能 数据格式
史上最简单的大模型教程之案例:哄哄模拟器(二)
史上最简单的大模型教程之案例:哄哄模拟器(二)
468 0