-
使用NuGet即可下载到最新免费的MVVMLight,安装之后,会有以下几个DLL被项目引用:
其中还依赖了一个微软的DLL——Microsoft.Practices.ServiceLocation.dll。
-
在使用过程中,**可能遇到的问题:**就是可能是由于MvvmLight没有及时更新,如果将图中的CommonServiceLocator升级到最新的2.x版本之后,它所依赖的ServiceLication的名称空间变为了CommonServiceLocator,导致安装MvvmLight之后自动生成的代码就出现了错误,
如果你使用了最新版本,那么就需要手动修改一下这个名称空间
:
-
安装完成MvvmLight之后,系统会自动生成一个ViewModel文件夹以及MainViewModel和ViewModelLocator两个文件,并将ViewModelLocator添加到了全局资源App.xaml中:
<Application x:Class="MvvmLightDemo.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:MvvmLightDemo" StartupUri="MainWindow.xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d1p1:Ignorable="d"
xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Application.Resources>
<ResourceDictionary>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:MvvmLightDemo.ViewModel" />
</ResourceDictionary>
</Application.Resources>
</Application>
这个类型有什么作用,要把它放到全局资源中?
- 在View层,即XAML文件中,不必直接引用ViewModel类型了,通过Locator中的Register进行关联
- 所有的View都可以到Locator中找到自己需要的VM层,这个Locator相当于一个索引器
- Locator层返回的VM层是单例形式的,避免了由于代码问题导致的内存泄漏
public class ViewModelLocator
public ViewModelLocator()
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<MainViewModel>();
public MainViewModel Main
return ServiceLocator.Current.GetInstance<MainViewModel>();
public static void Cleanup()
它继承自父类ObservableObject,实现了INotifyPropertyChanged和ICleanup,以实现:
- 当对象的属性发生变化的时候,会通知View层更新它的显示
- 在Page切换、标签页关闭等场景中,使用Clearup以及-=event释放不再需要的资源
在使用的过程中,需要我们调用ViewModelBase为我们提供的Set函数在属性的Set当中调用,即可实现通知View层的效果:
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System;
public class MainViewModel : ViewModelBase
private string m_LabelShow;
public string Label1Show
get { return m_LabelShow; }
set { Set(ref m_LabelShow, value); }
public MainViewModel()
Label1Show = "ShowOne";
至于MvvmLight的实现原理,以下代码可以表明MvvmLight到底做了些什么:
- 它帮助我们实现了RaisePropertyChanged方法
- 在属性值发生变化的时候,就可以发出通知
public class MvvmBase : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
protected virtual void SetAndNotifyIfChanged<T>(string propertyName, ref T oldValue, T newValue)
if (oldValue == null && newValue == null) return;
if (oldValue != null && oldValue.Equals(newValue)) return;
if (newValue != null && newValue.Equals(oldValue)) return;
oldValue = newValue;
RaisePropertyChanged(propertyName);
RelayCommand翻译过来就是“依赖命令”,相对于依赖属性,该类型主要作用就是让ViewModel层的类型具有处理依赖命令的能力。如果一个控件中包含了一个Icommand接口,那么就可以在MvvmLight架构下的VM层使用RelayCommand对依赖命令进行实现了
以下这个例子是利用RelayCommand实现一个前进后退按钮,可以导航控制Page页:
利用MvvmLight实现的优势就是:
- 前端XMAL编写和后端ViewModel编写能够完全解耦和,互不干扰
- ViewModel端直接控制自己的所有属性
View端:
<Window x:Class="MvvmLightDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MvvmLightDemo"
xmlns:vm="clr-namespace:MvvmLightDemo.ViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
DataContext="{Binding Source={StaticResource Locator}, Path=Main}">
<Grid.RowDefinitions>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="90*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0" >
<Button Command="{Binding NavToPrePage}">Nav To PrePage</Button>
<Button Command="{Binding NavToNextPage}">Nav To NextPage</Button>
</StackPanel>
<Frame Content="{Binding MainWindowFrame}" Grid.Row="1" NavigationUIVisibility="Hidden"></Frame>
</Grid>
</Window>
ViewModel端:
public class MainViewModel : ViewModelBase
public RelayCommand NavToNextPage { get; set; }
public RelayCommand NavToPrePage { get; set; }
private Frame m_MainWindowFrame;
public Frame MainWindowFrame
get { return m_MainWindowFrame; }
set { Set(ref m_MainWindowFrame, value); }
private Page m_MPage;
public Page MPage
get { return m_MPage; }
set { Set(ref m_MPage, value); }
private Page m_AttachPage;
public Page AttachPage
get { return m_AttachPage; }
set { Set(ref m_AttachPage, value); }
public MainViewModel()
NavToNextPage = new RelayCommand(NavNextPage);
NavToPrePage = new RelayCommand(NavPrePage);
MPage = new MainPage();
AttachPage = new PageTwo();
MainWindowFrame = new Frame();
MainWindowFrame.NavigationUIVisibility = System.Windows.Navigation.NavigationUIVisibility.Hidden;
MainWindowFrame.Content = MPage;
private void NavNextPage()
MainWindowFrame.Content = AttachPage;
private void NavPrePage()
MainWindowFrame.Content = MPage;
源代码可参见:https://github.com/visiontrail/CSharpKnowledge 在工程MvvmLightDemo工程当中,使用VS2015/VS2017编译
GetInstance(Type, string)
这是从容器中检索单个实例的核心方法。
此方法不得返回null。 它必须返回一个实现请求类型的实例,或者抛出一个ActivationException。 不允许其他任何异常类型(除了诸如ThreadAbortException之类的常规CLR规则外)。
该实现应设计为期望字符串key参数为null,并且必须将此解释为获取所请求类型的“默认”实例的请求。 “默认”的含义取决于基础容器及其配置方式。 长度为0的字符串被认为不同于null,实现者可以自由选择长度为0的字符串作为键的含义。
GetAllInstances(Type)
这是从容器中检索多个实例的核心方法。
如果容器不包含所请求类型的实例,则此方法务必返回长度为0
MVVM Light是WPF的一个mvvm框架,目前已经停止维护,适用于Net framework版本下的WPF程序,如果要在net5或者更新的net版本使用,可以使用新的CommunityToolkit.Mvvm包,它是 .NET 社区工具包的一部分,用法和MvvmLight类似。
WPF MVVM解析
介绍:下面界面是一个简易的加法计算器,其中包括三个数据属性(Value1,Value2,Sum)和两个命令属性(Save,Calculator),使用MVVM模式实现方法如下:
第一步:创建一个WPF项目,UI代码如下(其中的数据和命令绑定其实是后续添加的):
<Window x:Class="WPF_MVVM_Demo.MainWindow"
xml...
本篇我们着重介绍ViewModelBase,演示Set和RaisePropertyChanged方法的使用,以及就Cleanup方法释放资源展开讨论。
ICleanup 接口。
实现该接口的ViewModel需要在Cleanup方法里释放资源,特别是-= event
ObservableObject
该类实现了INotifyPropertyChanged接口,定义了一个可通知的对象基类,
小弟在一个TabItem里放了一个注册了消息的控件,每次在关闭标签页后再重新打开都会在一个属性的RaisePropertyChanged里报错,开始先是以为是初始化的错误,又以为是用了Ni控件的原因,折腾了两三天后还是找不出问题,只好先放弃了。
没想到今天在做父子窗口数据传递的时候,在网上搜到有文章说子窗口关闭的时候必须要Cleanup,反注册掉所有的消息,我一下子想起了这个问题。果断在控件的c
MvvmLight:
ICleanup 实现了这个接口的ViewModel当不需要使用时,可以在Cleanup方法中去释放资源
ObservableObject该类实现了INotifyPropertyChanged接口,定义了一个可通知的对象基类,供ViewModelBase继承 ,
ViewModelBase属于主体库,继承自Observabl
一、MVVM 和 MVVMLight介绍
MVVM是Model-View-ViewModel的简写。类似于目前比较流行的MVC、MVP设计模式,主要目的是为了分离视图(View)和模型(Model)的耦合。
它是一种极度优秀的设计模式,但并非框架级别的东西,由MVP(Model-View-Presenter)模式与WPF结合的应用方式时发展演变过来的一种新型架构。
立足于原有MVP框架并且把...
protected virtual void RaisePropertyChanging<T>(Expression<Func<T>> propertyExpression);
protected bool Set<T>(Expression<Func<T>> propertyExpression,...
MvvmLight是比较流行的MVVM框架,相对较为简单易用。可能正因为简单,对应的帮助文档不多,对初学者就不够友好了。这里会用几篇随笔,就个人对MvvmLight的使用经验,来做一个入门的介绍。
第一步我们先找到并下载MvvmLight的最新版,我个人倾向使用NuGet。这里顺便吐槽一下,MvvmLight貌似并未在Github上创建项目,虽然作者对MS深深的爱让我感动,不过也不要排...
wpf的精华就是mvvm,viewmodel与view以及db.cs数据库操作类的关系,使得mianwondow几乎不用写什么代码,逻辑都放在viewmodel里,db里存放一些基础数据操作方法。内附源码链接。
先展示一下界面:
新增以及修改界面
先展示一下解决方案,如下图,db文件夹下存放的mydb.cs是数据库基本操作,model下的student.cs是实体类,view文件夹下是视图(界面)文件,viewmodel文件夹下的mianviewmodel.cs是vm文...
三个控件同时绑定了一个变量(点击按钮通过MessageBox显示变量值),通过NuGet下载MVVM Light:
MainViewModel类代码:
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
namespace WPF0416.ViewModel
pub...
首先,在你的自定义控件类 (示例:以上代码简化了官方方法的流程,以便你不用再去额外输入不必要的参数,并提前对 sender 进行类型转换。此后,添加一个属性只需要添加以下代码即可,相比传统方法看起来会非常直观,非常省事。以上代码中,defaultValue 可以为 null,但使用 null 作为默认值必须声明泛型类型。