前言
作者:浪子花梦,一个有趣的程序员 ~
此文将完成Bing搜索菜单的功能(带参数的命令绑定),利用消息解除ViewModel与View之间的耦合性,并且利用一个非常重要的技术——依赖注入(解决ViewModel与ViewModel之间的耦合性 . . .
前文如下所示:
【WPF高仿 Windows记事本】开发日记 (一) UI布局(帮助菜单功能实现
)
【WPF高仿 Windows记事本】开发日记 (二) 初步使用MVVM模式设计 帮助菜单 的三个命令
【WPF高仿 Windows记事本】开发日记 (三) 完善所有菜单的命令绑定并创建Models层的设计
【WPF高仿 Windows记事本】开发日记 (四) 菜单命令快捷键实现,实现查看菜单功能(三层架构初步使用
)
【WPF高仿 Windows记事本】开发日记 (五) 使用成熟的自动更新代码(ObservableObject)、实现是否显示状态栏功能、鼠标的滚轮命令绑定(查看菜单功能实现
)
【WPF高仿 Windows记事本】开发日记 (六) 自动换行、滚动条命令绑定,实现字体模式的选择功能(格式菜单功能实现
)
【WPF高仿 Windows记事本】开发日记 (七) 编辑菜单中的内置命令使用,查看与替换的窗口设计(包含窗口变为对话框)
.
1)在命令中传入一个命令参数,这个参数是TextBox类型:
.
.
2)创建一个有命令参数的命令:
方法如下所示所示:
这些操作需要的类在如下的链接之中:
WPF使用成熟的命令系统(带参数)
.
.
3)利用消息来解除ViewModel与View之间的耦合性,操作方法如下所示:
WPF利用消息解决ViewModel与View之间的耦合性
.
.
4)利用依赖注入解除程序间的耦合:
我们MainViewModels中定义其它几个业务逻辑类,这就造成了很大的耦合性,我们利用loc可以可效的解决这种耦合性,如下所示:
首先我们需要如下的几个辅助类:
- SimpleIoc
- ISimpleIoc
- IServiceLocator
- ActivationException
- PreferredConstructorAttribute
- ServiceLocator
- ViewModelLocator(一些需要依赖注入的类型)
- FindWindowModel(查找窗口类,单独的数据层)
- ReplaceWindowModel(替换窗口类,单独的数据层)
我们只需要操作最后三个类就行,其它的类是在辅助ViewModelLocator类的,ViewModelLocator 类的代码如下所示:
using Notepad_WPF.Helpers;
using Notepad_WPF.Models;
namespace Notepad_WPF.ViewModels
{
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
// 将这些类型放到容器中
SimpleIoc.Default.Register<DocumentModel>();
SimpleIoc.Default.Register<EditViewModel>();
SimpleIoc.Default.Register<FileViewModel>();
SimpleIoc.Default.Register<FormatViewModel>();
SimpleIoc.Default.Register<ViewViewModel>();
SimpleIoc.Default.Register<HelpViewModel>();
// 将查找与替换的窗口数据类注册到 loc中
SimpleIoc.Default.Register<FindWindowModel>();
SimpleIoc.Default.Register<ReplaceWindowModel>();
}
// 在容器中获取指定类型的实例,然后注入到其它对象中,创建对应的实例时
// 他们会自动查看DocumentModel类型,使用的都是同一份 他们会自动查看DocumentModel类型
public DocumentModel DocumentModel => ServiceLocator.Current.GetInstance<DocumentModel>();
public EditViewModel EditViewModel => ServiceLocator.Current.GetInstance<EditViewModel>();
public FileViewModel FileViewModel => ServiceLocator.Current.GetInstance<FileViewModel>();
public FormatViewModel FormatViewModel => ServiceLocator.Current.GetInstance<FormatViewModel>();
public ViewViewModel ViewViewModel => ServiceLocator.Current.GetInstance<ViewViewModel>();
public HelpViewModel HelpViewModel => ServiceLocator.Current.GetInstance<HelpViewModel>();
public FindWindowModel FindWindowModel => ServiceLocator.Current.GetInstance<FindWindowModel>();
public ReplaceWindowModel ReplaceWindowModel => ServiceLocator.Current.GetInstance<ReplaceWindowModel>();
public static void Cleanup()
{
}
}
}
我们在App.xaml 中定义如下的资源:
<Application.Resources>
<ResourceDictionary>
<vm:ViewModelLocator xmlns:vm="clr-namespace:Notepad_WPF" x:Key="Locator"/>
</ResourceDictionary>
</Application.Resources>
然后我们就可以在主xaml文件中引用了,如下所示:
其它的数据不需要任何的改变,然后我们在定义查看和替换窗口的业务逻辑类,如下所示:
其中,有一个按钮的点击命令,还有一个数据层的类,这个类是Locator中的DocumentModel,所以他们用的是同一个类,在查找窗口的xaml代码中,我们这样引用:
在控件容器中这样引用 DocumentModel:
这样我们其它的数据绑定就不需要任何的改变,如果我们想给按钮绑定他需要的命令,则如下所示: