百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

界面控件DevExpress WinForm - MVVM服务讲解(二)

ccwgpt 2025-04-06 14:20 15 浏览 0 评论

DevExpress Universal Subscription官方最新版免费下载试用,历史版本下载,在线文档和帮助文件下载-慧都网

考虑像显示来自 ViewModel 的通知(例如,消息框)这样的微不足道的任务,作为可视化元素,任何消息框实际上都是视图的一部分。 因此,如果你直接从 ViewModel 显示消息框(定义一个调用 MessageBox.Show() 方法的命令),这个简单的代码将破坏主要的MVVM概念 - ViewModels不能引用Views,并使其无法编写ViewModel的单元测试。为了解决这个困难,DevExpress MVVM 框架实现了服务。

服务是一种 IOC 模式,它删除了 ViewModel 和 View 层之间的任何引用。 在代码中,服务是在 ViewModel 代码中使用的接口,没有任何关于“何时”和“如何”实现该接口的假设。

您可以实现自己的自定义服务以及使用 DevExpress Services,无论您使用什么服务,通用工作流程都保持不变:

  • 在代码中定义服务(如果您使用的是 DevExpress 已经实现的服务,则跳过);
  • 在特定的视图中注册它;
  • 在ViewModel中检索服务并使用其方法。

自定义服务

对于自定义服务,您首先需要在单独类中的某处实现此服务,例如应用程序具有带有 Notify 方法的自定义接口 IMyNotificationService。

C#

//View
public interface IMyNotificationService {
void Notify(string message);
}

VB.NET

'View
Public Interface IMyNotificationService
Sub Notify(ByVal message As String)
End Interface

然后,实现此接口的自定义服务 CustomService1 将如下所示。

C#

//Service1.cs
class CustomService1 : IMyNotificationService {
void IMyNotificationService.Notify(string message) {
System.Windows.Forms.MessageBox.Show(message, "Service1");
}
}

VB.NET

'Service1.vb
Friend Class CustomService1
Implements IMyNotificationService

Private Sub IMyNotificationService_Notify(ByVal message As String) Implements IMyNotificationService.Notify
System.Windows.Forms.MessageBox.Show(message, "Service1")
End Sub
End Class

作为变体,创建另一个实现相同接口但使用不同方法重载的服务。

C#

//Service2.cs
class CustomService2 : IMyNotificationService {
void IMyNotificationService.Notify(string message) {
System.Windows.Forms.MessageBox.Show(message, "Service2");
}
}

VB.NET

'Service2.vb
Friend Class CustomService2
Implements IMyNotificationService

Private Sub IMyNotificationService_Notify(ByVal message As String) Implements IMyNotificationService.Notify
System.Windows.Forms.MessageBox.Show(message, "Service2")
End Sub
End Class

在 ViewModel 代码中检索自定义服务的属性将如下所示。

C#

//ViewModel
public virtual IMyNotificationService Service {
get { throw new NotImplementedException(); }
}

public virtual IMyNotificationService AnotherService {
get { throw new NotImplementedException(); }
}

VB.NET

'ViewModel
Public Overridable ReadOnly Property Service() As IMyNotificationService
Get
Throw New NotImplementedException()
End Get
End Property

Public Overridable ReadOnly Property AnotherService() As IMyNotificationService
Get
Throw New NotImplementedException()
End Get
End Property

这是可以绑定到 UI 元素(例如,按钮)的 DoSomething 方法,它将显示具有相同文本的两条消息。

C#

//ViewModel
public void DoSomething() {
Service.Notify("Hello");
AnotherService.Notify("Hello");
}

VB.NET

'ViewModel
Public Sub DoSomething()
Service.Notify("Hello")
AnotherService.Notify("Hello")
End Sub

最后,在视图中注册您的自定义服务。 由于这些是您自己的自定义服务,因此不存在用于注册这些服务的预定义静态 MVVMContext 方法。 相反,调用本地 MvvmContext 实例的 RegisterService 方法。

C#

//View
mvvmContext1.RegisterService(new CustomService1());
mvvmContext1.RegisterService(new CustomService2());

VB.NET

'View
mvvmContext1.RegisterService(New CustomService1())
mvvmContext1.RegisterService(New CustomService2())

提示:注册后,服务在分层树中占据特定位置。每当框架需要服务时,它就会从树的底部开始寻找,向上移动直到找到合适的服务。前面有提到很多现成的服务已经在静态容器中注册了,这些服务位于层次结构的最顶层,如果框架没有在较低级别找到任何自定义服务,则会使用这些服务。如果这两个默认服务都不存在,则会发生异常。在此示例中,两个自定义服务都注册在同一层次结构级别上。由于这两个服务实现了相同的 IMyNotificationService 服务,因此在调用 Service 或 AnotherService 对象的 Notify 方法时,它们都被视为合适的服务。但是 CustomService2 是最后注册的,因此它更靠近层次结构底部,并且总是首先被框架“找到”。您可以欺骗此机制并使用 RegisterDefaultService 方法注册 CustomService2,这将在层次结构顶部的静态容器中注册您的 CustomService2,并使 CustomSerive1 成为最底层的服务。之后,框架将始终选择 CustomService1。

为了解决这个问题,您可以定义服务密钥。key是标记特定服务的字符串标识符,对于 POCO ViewModel,您可以将服务密钥设置为 [ServiceProperty] 属性的参数。

C#

[ServiceProperty(Key="Service1")]
public virtual IMyNotificationService Service {
get { throw new NotImplementedException(); }
}

[ServiceProperty(Key = "Service2")]
public virtual IMyNotificationService AnotherService {
get { throw new NotImplementedException(); }
}

VB.NET


Public Overridable ReadOnly Property Service() As IMyNotificationService
Get
Throw New NotImplementedException()
End Get
End Property


Public Overridable ReadOnly Property AnotherService() As IMyNotificationService
Get
Throw New NotImplementedException()
End Get
End Property

对于非 POCO ViewModel,可以将服务密钥设置为 GetService 扩展方法的参数。

C#

public IServiceInterface MyService {
get { return this.GetService("MyServiceKey"); }
}

VB.NET

Public ReadOnly Property MyService() As IServiceInterface
Get
Return Me.GetService(Of IServiceInterface )("MyServiceKey")
End Get
End Property

现在,您必须使用这些唯一密钥注册您的自定义服务,所有 Register 方法都有相应的重载来做到这一点。

C#

mvvmContext1.RegisterService("Service1", new CustomService1());
mvvmContext1.RegisterService("Service2", new CustomService2());

VB.NET

mvvmContext1.RegisterService("Service1", New CustomService1())
mvvmContext1.RegisterService("Service2", New CustomService2())

因此,当您调用 Notify 方法时,框架将不会混淆应该使用哪个 IMyNotificationService 服务实现。 相反它将采用标有您的自定义密钥的确切服务,例如,AnotherService 属性将寻找标有“Service2”键的服务,并找到已注册的 CustomService2 服务。 与 Service 属性相同,它将使用 CustomService1 服务,因为它标有“Service1”键。

如果您现在测试应用程序,您将看到两个消息框现在显示不同的标题,因为它们是由不同服务的方法显示的。

DevExpress WinForm

DevExpress WinForm拥有180+组件和UI库,能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任!



相关推荐

团队管理“布阵术”:3招让你的团队战斗力爆表!

为何古代军队能够以一当十?为何现代企业有的团队高效似“特种部队”,有的却松散若“游击队”?**答案正隐匿于“布阵术”之中!**今时今日,让我们从古代兵法里萃取3个核心要义,助您塑造一支战斗力爆棚的...

知情人士回应字节大模型团队架构调整

【知情人士回应字节大模型团队架构调整】财联社2月21日电,针对原谷歌DeepMind副总裁吴永辉加入字节跳动后引发的团队调整问题,知情人士回应称:吴永辉博士主要负责AI基础研究探索工作,偏基础研究;A...

豆包大模型团队开源RLHF框架,训练吞吐量最高提升20倍

强化学习(RL)对大模型复杂推理能力提升有关键作用,但其复杂的计算流程对训练和部署也带来了巨大挑战。近日,字节跳动豆包大模型团队与香港大学联合提出HybridFlow。这是一个灵活高效的RL/RL...

创业团队如何设计股权架构及分配(创业团队如何设计股权架构及分配方案)

创业团队的股权架构设计,决定了公司在随后发展中呈现出的股权布局。如果最初的股权架构就存在先天不足,公司就很难顺利、稳定地成长起来。因此,创业之初,对股权设计应慎之又慎,避免留下巨大隐患和风险。两个人如...

消息称吴永辉入职后引发字节大模型团队架构大调整

2月21日,有消息称前谷歌大佬吴永辉加入字节跳动,并担任大模型团队Seed基础研究负责人后,引发了字节跳动大模型团队架构大调整。多名原本向朱文佳汇报的算法和技术负责人开始转向吴永辉汇报。简单来说,就是...

31页组织效能提升模型,经营管理团队搭建框架与权责定位

分享职场干货,提升能力!为职场精英打造个人知识体系,升职加薪!31页组织效能提升模型如何拿到分享的源文件:请您关注本头条号,然后私信本头条号“文米”2个字,按照操作流程,专人负责发送源文件给您。...

异形柱结构(异形柱结构技术规程)

下列关于混凝土异形柱结构设计的说法,其中何项正确?(A)混凝土异形柱框架结构可用于所有非抗震和抗震设防地区的一般居住建筑。(B)抗震设防烈度为6度时,对标准设防类(丙类)采用异形柱结构的建筑可不进行地...

职场干货:金字塔原理(金字塔原理实战篇)

金字塔原理的适用范围:金字塔原理适用于所有需要构建清晰逻辑框架的文章。第一篇:表达的逻辑。如何利用金字塔原理构建基本的金字塔结构受众(包括读者、听众、观众或学员)最容易理解的顺序:先了解主要的、抽象的...

底部剪力法(底部剪力法的基本原理)

某四层钢筋混凝土框架结构,计算简图如图1所示。抗震设防类别为丙类,抗震设防烈度为8度(0.2g),Ⅱ类场地,设计地震分组为第一组,第一自振周期T1=0.55s。一至四层的楼层侧向刚度依次为:K1=1...

结构等效重力荷载代表值(等效重力荷载系数)

某五层钢筋混凝土框架结构办公楼,房屋高度25.45m。抗震设防烈度8度,设防类别丙类,设计基本地震加速度0.2g,设计地震分组第二组,场地类别为Ⅱ类,混凝土强度等级C30。该结构平面和竖向均规则。假定...

体系结构已成昭告后世善莫大焉(体系构架是什么意思)

实践先行也理论已初步完成框架结构留余后人后世子孙俗话说前人栽树后人乘凉在夏商周大明大清民国共和前人栽树下吾之辈已完成结构体系又俗话说青出于蓝而胜于蓝各个时期任务不同吾辈探索框架结构体系经历有限肯定发展...

框架柱抗震构造要求(框架柱抗震设计)

某现浇钢筋混凝土框架-剪力墙结构高层办公楼,抗震设防烈度为8度(0.2g),场地类别为Ⅱ类,抗震等级:框架二级,剪力墙一级,混凝土强度等级:框架柱及剪力墙C50,框架梁及楼板C35,纵向钢筋及箍筋均采...

梁的刚度、挠度控制(钢梁挠度过大会引起什么原因)

某办公楼为现浇钢筋混凝土框架结构,r0=1.0,混凝土强度等级C35,纵向钢筋采用HRB400,箍筋采用HPB300。其二层(中间楼层)的局部平面图和次梁L-1的计算简图如图1~3(Z)所示,其中,K...

死要面子!有钱做大玻璃窗,却没有钱做“柱和梁”,不怕房塌吗?

活久见,有钱做2层落地大玻璃窗,却没有钱做“柱子和圈梁”,这样的农村自建房,安全吗?最近刷到个魔幻施工现场,如下图,这栋5开间的农村自建房,居然做了2个全景落地窗仔细观察,这2个落地窗还是飘窗,为了追...

不是承重墙,物业也不让拆?话说装修就一定要拆墙才行么

最近发现好多朋友装修时总想拆墙“爆改”空间,别以为只要避开承重墙就能随便砸!我家楼上邻居去年装修,拆了阳台矮墙想扩客厅,结果物业直接上门叫停。后来才知道,这种配重墙拆了会让阳台承重失衡,整栋楼都可能变...

取消回复欢迎 发表评论: