轻量级的MVVM-MVVM Light
使用 NuGet 查找和安装 MVVM Light
要在 NuGet 中查找 MVVM Light,请按照下列步骤操作:
- 在 Visual Studio 中打开您的项目。
- 右键单击 "引用",然后从上下文菜单中选择“管理Nuget程序包”。
- 在“Manage Nuget Packages”对话框中,选择右侧的“Online”。
- 在搜索字段中,输入“mvvmlight”。
- 选择 MVVM Light 包并按下 Install 按钮(顶部选项;其他选项将在下面进一步解释)。
完成这些步骤后,您的项目已进行以下更改:
- 添加了“packages”文件夹,其中包含以下库。请注意,此文件夹已添加到项目结构的根目录中,并且不会出现在解决方案资源管理器中。
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CommonServiceLocator" version="2.0.2" targetFramework="net472" />
<package id="MvvmLight" version="5.4.1.1" targetFramework="net472" />
<package id="MvvmLightLibs" version="5.4.1.1" targetFramework="net472" />
</packages>
- 添加了一个带有两个附加类的 ViewModel 文件夹:
- ViewModelLocator.cs
- MainViewModel.cs
- App.xaml 文件已通过添加 ViewModelLocator 作为全局资源进行了修改。
<Application
x:Class="MVVMDemo.App"
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:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MVVMDemo"
d1p1:Ignorable="d"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:MVVMDemo.ViewModel" />
</ResourceDictionary>
</Application.Resources>
</Application>
在 XAML 中绑定 DataContext
使用新的文件结构,ViewModelLocator 在 App.xaml(全局资源)中公开并可用作 DataContext 绑定的源。
也已添加到项目中的 MainViewModel 作为属性在 ViewModelLocator 中公开。有关此架构的更多详细信息,请参阅了解 MVVM 模式和深入研究 MVVM。
注意:如果您的项目中不需要 MainViewModel,请随意删除此类。
要将 MainViewModel 用作 MainPage 或 MainWindow 的 DataContext,请使用以下步骤:
- 打开 MainPage.xaml 或 MainWindow.xaml。
- 将以下行添加到 MainPage/MainWindow 的开始标记:
DataContext="{Binding Main, Source={StaticResource Locator}}"
从现在开始,MainPage/MainWindow 的 DataContext 设置为 ViewModelLocator 公开的 MainViewModel 实例。可以使用不同的视图/视图模型对随意重复这些步骤。
创建自己的MVVM实例
完成《使用 NuGet 查找和安装 MVVM Light》后
此时编译会产生错误
需要删除
此时编译可以可启动。
作为范例,我们继续删除
新建Model(后台)、View(前台UI)、ViewModel(前后UI与后台关联处理)三个文件夹。
并创建自己所需的Model、View、ViewModel文件。
修改启动
设计Model(Model1.cs)
using GalaSoft.MvvmLight;//添加
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MVVMDemo.Model
{
public class Model1:ViewModelBase //根据需求派生
{
private int number1;
private int number2;
private int sum;
public int Number1 { get => number1; set { number1 = value;RaisePropertyChanged(); } } //RaisePropertyChanged通知变更
public int Number2 { get => number2; set { number2 = value; RaisePropertyChanged(); } }
public int Sum { get => sum; set { sum = value; RaisePropertyChanged(); } }
public void SumExe()
{
Sum = Number1 + Number2;
//System.Windows.MessageBox.Show(Number1+"\n"+ Number2 +"\n" + Sum + "\n");
}
}
}
设计View(UI),绑定数据源、绑定命令
<Window
x:Class="MVVMDemo.View.View1"
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:local="clr-namespace:MVVMDemo.View"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="View1"
Width="300"
Height="250"
mc:Ignorable="d">
<StackPanel>
<TextBox Width="250" Height="40" Margin="5" Text="{Binding ModelProp.Number1}" />
<TextBox Width="250" Height="40" Margin="5" Text="{Binding ModelProp.Number2}" />
<TextBox Width="250" Height="40" Margin="5" Text="{Binding ModelProp.Sum}" />
<Button
Width="250"
Height="40"
Margin="5"
Command="{Binding addCommand}"
Content="Add" />
</StackPanel>
</Window>
处理ViewModel
这里提下,Binding model1.Number1是不行的,需要用属性暴露。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GalaSoft.MvvmLight; //添加
using GalaSoft.MvvmLight.Command;//添加
using MVVMDemo.Model; //添加
namespace MVVMDemo.ViewModel
{
public class ViewModel1 : ViewModelBase //必须派生自ViewModelBase
{
public ViewModel1()
{
ModelProp = new Model1() ;
addCommand = new RelayCommand(ModelProp.SumExe);
}
private Model1 model1;
public RelayCommand addCommand { get; set; }
public Model1 ModelProp { get => model1; set => model1 = value; }
}
}
最后,把ViewModel实例化,作为View的Context
using MVVMDemo.ViewModel; //添加ViewModel引用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace MVVMDemo.View
{
/// <summary>
/// View1.xaml 的交互逻辑
/// </summary>
public partial class View1 : Window
{
public View1()
{
InitializeComponent();
this.DataContext = new ViewModel1();
}
}
}
MVVM有什么用?
MVVM即Model-View-ViewModel
Model:应用程序中处理数据逻辑的一部分,通常用来模型对象对数据库的存取等操作
View:视图部分,通常指前端页面用来对用户展示的一部分
可以将ViewMode看作是Model和View的连接桥,View可以通过事件绑定Model,Model可以通过数据绑定View,通过ViewMode可以实现数据和视图的完全分离
MVVM主要优势是实现了UI和逻辑的开发解耦。
范例:客户对此UI不满意,希望number1和number2希望用slider输入
修改UI,新增View2,修改View2
<Window
x:Class="MVVMDemo.View.View2"
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:local="clr-namespace:MVVMDemo.View"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="View2"
Width="300"
Height="250"
mc:Ignorable="d">
<StackPanel>
<Slider Width="250" Height="40" Margin="5" Maximum="10" Minimum="0" IsSnapToTickEnabled="True" TickFrequency="1" AutoToolTipPlacement="BottomRight" Value="{Binding ModelProp.Number1}" />
<Slider Width="250" Height="40" Margin="5" Maximum="10" Minimum="0" IsSnapToTickEnabled="True" TickFrequency="1" AutoToolTipPlacement="BottomRight" Value="{Binding ModelProp.Number2}" />
<TextBox Width="250" Height="40" Margin="5" Text="{Binding ModelProp.Sum}" />
<Button
Width="250"
Height="40"
Margin="5"
Command="{Binding addCommand}"
Content="Add" />
</StackPanel>
</Window>
using MVVMDemo.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace MVVMDemo.View
{
/// <summary>
/// View2.xaml 的交互逻辑
/// </summary>
public partial class View2 : Window
{
public View2()
{
InitializeComponent();
this.DataContext = new ViewModel1();
}
}
}
修改启动项目
<Application
x:Class="MVVMDemo.App"
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:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MVVMDemo"
d1p1:Ignorable="d"
StartupUri="View\View2.xaml">
<Application.Resources>
<ResourceDictionary />
</Application.Resources>
</Application>
运行
结果
只修改了View,甚至没有修改ViewModel。
正常修改View,基本都需要修改ViewModel。
参考资料
https://docs.microsoft.com/en-us/archive/msdn-magazine/2013/may/mvvm-commands-relaycommands-and-eventtocommand
https://docs.microsoft.com/en-us/archive/msdn-magazine/2013/february/mvvm-ioc-containers-and-mvvm