翻譯|使用教程|編輯:龔雪|2021-12-30 10:18:05.220|閱讀 279 次
概述:DevExpress WinForm創(chuàng)建的應用程序可利用MVVM設(shè)計模式,本文主要介紹服務功能,歡迎下載最新版體驗!
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關(guān)鏈接:
獲取工具下載 - DevExpress WinForm v21.2
考慮像顯示來自 ViewModel 的通知(例如,消息框)這樣的微不足道的任務,作為可視化元素,任何消息框?qū)嶋H上都是視圖的一部分。 因此,如果你直接從 ViewModel 顯示消息框(定義一個調(diào)用 MessageBox.Show() 方法的命令),這個簡單的代碼將破壞主要的MVVM概念 - ViewModels不能引用Views,并使其無法編寫ViewModel的單元測試。為了解決這個困難,DevExpress MVVM 框架實現(xiàn)了服務。
服務是一種 IOC 模式,它刪除了 ViewModel 和 View 層之間的任何引用。 在代碼中,服務是在 ViewModel 代碼中使用的接口,沒有任何關(guān)于“何時”和“如何”實現(xiàn)該接口的假設(shè)。
您可以實現(xiàn)自己的自定義服務以及使用 DevExpress Services,無論您使用什么服務,通用工作流程都保持不變:
對于自定義服務,您首先需要在單獨類中的某處實現(xiàn)此服務,例如應用程序具有帶有 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
然后,實現(xiàn)此接口的自定義服務 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
作為變體,創(chuàng)建另一個實現(xiàn)相同接口但使用不同方法重載的服務。
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
最后,在視圖中注冊您的自定義服務。 由于這些是您自己的自定義服務,因此不存在用于注冊這些服務的預定義靜態(tài) MVVMContext 方法。 相反,調(diào)用本地 MvvmContext 實例的 RegisterService 方法。
C#
//View mvvmContext1.RegisterService(new CustomService1()); mvvmContext1.RegisterService(new CustomService2());
VB.NET
'View mvvmContext1.RegisterService(New CustomService1()) mvvmContext1.RegisterService(New CustomService2())
提示:注冊后,服務在分層樹中占據(jù)特定位置。每當框架需要服務時,它就會從樹的底部開始尋找,向上移動直到找到合適的服務。前面有提到很多現(xiàn)成的服務已經(jīng)在靜態(tài)容器中注冊了,這些服務位于層次結(jié)構(gòu)的最頂層,如果框架沒有在較低級別找到任何自定義服務,則會使用這些服務。如果這兩個默認服務都不存在,則會發(fā)生異常。在此示例中,兩個自定義服務都注冊在同一層次結(jié)構(gòu)級別上。由于這兩個服務實現(xiàn)了相同的 IMyNotificationService 服務,因此在調(diào)用 Service 或 AnotherService 對象的 Notify 方法時,它們都被視為合適的服務。但是 CustomService2 是最后注冊的,因此它更靠近層次結(jié)構(gòu)底部,并且總是首先被框架“找到”。您可以欺騙此機制并使用 RegisterDefaultService 方法注冊 CustomService2,這將在層次結(jié)構(gòu)頂部的靜態(tài)容器中注冊您的 CustomService2,并使 CustomSerive1 成為最底層的服務。之后,框架將始終選擇 CustomService1。
為了解決這個問題,您可以定義服務密鑰。key是標記特定服務的字符串標識符,對于 POCO ViewModel,您可以將服務密鑰設(shè)置為 [ServiceProperty] 屬性的參數(shù)。
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
<ServiceProperty(Key:="Service1")> Public Overridable ReadOnly Property Service() As IMyNotificationService Get Throw New NotImplementedException() End Get End Property <ServiceProperty(Key := "Service2")> Public Overridable ReadOnly Property AnotherService() As IMyNotificationService Get Throw New NotImplementedException() End Get End Property
對于非 POCO ViewModel,可以將服務密鑰設(shè)置為 GetService 擴展方法的參數(shù)。
C#
public IServiceInterface MyService { get { return this.GetService<IServiceInterface >("MyServiceKey"); } }
VB.NET
Public ReadOnly Property MyService() As IServiceInterface Get Return Me.GetService(Of IServiceInterface )("MyServiceKey") End Get End Property
現(xiàn)在,您必須使用這些唯一密鑰注冊您的自定義服務,所有 Register 方法都有相應的重載來做到這一點。
C#
mvvmContext1.RegisterService("Service1", new CustomService1()); mvvmContext1.RegisterService("Service2", new CustomService2());
VB.NET
mvvmContext1.RegisterService("Service1", New CustomService1()) mvvmContext1.RegisterService("Service2", New CustomService2())
因此,當您調(diào)用 Notify 方法時,框架將不會混淆應該使用哪個 IMyNotificationService 服務實現(xiàn)。 相反它將采用標有您的自定義密鑰的確切服務,例如,AnotherService 屬性將尋找標有“Service2”鍵的服務,并找到已注冊的 CustomService2 服務。 與 Service 屬性相同,它將使用 CustomService1 服務,因為它標有“Service1”鍵。
如果您現(xiàn)在測試應用程序,您將看到兩個消息框現(xiàn)在顯示不同的標題,因為它們是由不同服務的方法顯示的。
DevExpress WinForm擁有180+組件和UI庫,能為Windows Forms平臺創(chuàng)建具有影響力的業(yè)務解決方案。DevExpress WinForms能完美構(gòu)建流暢、美觀且易于使用的應用程序,無論是Office風格的界面,還是分析處理大批量的業(yè)務數(shù)據(jù),它都能輕松勝任!
更多產(chǎn)品正版授權(quán)詳情及優(yōu)惠,歡迎咨詢
DevExpress技術(shù)交流群5:742234706 歡迎一起進群討論
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@ke049m.cn
文章轉(zhuǎn)載自:慧都網(wǎng)