翻譯|使用教程|編輯:龔雪|2021-12-30 10:18:05.220|閱讀 272 次
概述:DevExpress WinForm創建的應用程序可利用MVVM設計模式,本文主要介紹服務功能,歡迎下載最新版體驗!
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
獲取工具下載 - DevExpress WinForm v21.2
考慮像顯示來自 ViewModel 的通知(例如,消息框)這樣的微不足道的任務,作為可視化元素,任何消息框實際上都是視圖的一部分。 因此,如果你直接從 ViewModel 顯示消息框(定義一個調用 MessageBox.Show() 方法的命令),這個簡單的代碼將破壞主要的MVVM概念 - ViewModels不能引用Views,并使其無法編寫ViewModel的單元測試。為了解決這個困難,DevExpress MVVM 框架實現了服務。
服務是一種 IOC 模式,它刪除了 ViewModel 和 View 層之間的任何引用。 在代碼中,服務是在 ViewModel 代碼中使用的接口,沒有任何關于“何時”和“如何”實現該接口的假設。
您可以實現自己的自定義服務以及使用 DevExpress Services,無論您使用什么服務,通用工作流程都保持不變:
對于自定義服務,您首先需要在單獨類中的某處實現此服務,例如應用程序具有帶有 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
<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,可以將服務密鑰設置為 GetService 擴展方法的參數。
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
現在,您必須使用這些唯一密鑰注冊您的自定義服務,所有 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擁有180+組件和UI庫,能為Windows Forms平臺創建具有影響力的業務解決方案。DevExpress WinForms能完美構建流暢、美觀且易于使用的應用程序,無論是Office風格的界面,還是分析處理大批量的業務數據,它都能輕松勝任!
更多產品正版授權詳情及優惠,歡迎咨詢
DevExpress技術交流群5:742234706 歡迎一起進群討論
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:慧都網