2009-02-10 88 views
7

編輯:接受克里斯霍姆斯的迴應,但總是準備重構,如果有人想出更好的方法!謝謝!模型視圖演示者,如何在視圖之間傳遞實體?

用MVP做一些winforms什麼是將實體傳遞給另一個視圖的最佳方式。

假設我有一個CustomerSearchView/Presenter,在doubleClick上我想顯示CustomerEditView/Presenter。我不希望我的觀點知道模型,所以我不能創建一個參數爲ICustomer的ctor。

我的反射會,

CustomerSearchView創建一個新的CustomerEditView,它創造它自己的主持人。 然後我CustomerSearchView會做這樣的事情:

var customerEditView = new CustomerEditView(); 
customerEditView.Presenter.Customer = this.Presenter.SelectedCustomer; 

其他可行的方法是一個CustomerDTO類,並作出CustomerEditView接受那些CustomerDTO之一,但我認爲這是一個很大的工作,簡單的東西。

對不起,基本的問題,但所有的例子我能找到從來沒有達到這一點,這是一個棕地項目,到目前爲止,是給我頭痛所使用的方法...

回答

4

我不知道你是如何展示你的觀點的,所以在這裏給你一些具體的建議有點困難。這就是我以前做過這種事情的原因:

我們所做的就是讓CustomerSearchViewPresenter觸發OpenCustomer(customerId)這樣的事件。 (假設你的搜索視圖只有少量客戶數據,而customerId就是其中之一,如果你的搜索視圖有整個客戶對象列表,那麼你可以調用OpenCustomer(customer)。但是我不會構建一個搜索視圖,並允許它填充整個對象...我們保持我們的搜索視圖在數據方面輕量級。)

應用程序中的其他位置是一個事件處理程序,用於偵聽OpenCustomer()事件並執行任務創建一個新的CustomerEditView w/Presenter(並且我將推遲到我的IoC容器爲我做這些事情,所以我不必在任何地方使用「new」關鍵字)。一旦創建了視圖,我們可以將id(或客戶對象)傳遞給新的CustomerEditView,然後顯示它。

該類負責列舉OpenCustomer()事件並執行CustomerEditView的創建,通常是我們應用程序中的某種Controller類。

爲了進一步簡化這種情況下,我做了這個法子:我同時創建CustomerSearchView(&主持人)和CustomerEditView(&主持人)時,應用程序或模塊啓動。當CustomerSearchView需要打開客戶進行編輯時,CustomerEditView將成爲OpenCustomer事件的響應者,並將數據加載到自身中,並知道如何在任何它應該執行的容器中展示自己。

所以有多種方法可以做到這一點。

1

如何:

//In CustomerSearchPresenter 
var presenter = new CustomerEditPresenter(); 
var customerEditView = new CustomerEditView(presenter); 
presenter.SetCustomer(customer); 

//In CustomerEditPresenter 
public void SetCustomer(customer) 
{ 
    View.Name = customer.Name; 
    View.Id = customer.Id; 
    ... 
} 

在認爲您的客戶搜索視圖應該委託給其發言人,您需要執行一個操作。

+0

您在上面拼寫爲「演示者」爲「演示者」。 – 2009-02-10 20:57:13

+0

好,就像我說的,除了你使用一種方法,而不是一個屬性來設置客戶。謝謝。 – pmlarocque 2009-02-11 13:43:55

+0

區別在於誰有什麼責任。在您的示例中,設置視圖代碼中的客戶意味着視圖知道如何獲得客戶。這應該留給主持人。 – 2009-02-11 16:06:22

0

有幾個關鍵的見解得到任何MVP代碼的自然流量:

  1. 這是驅動的觀點,而不是周圍的其他方式的主持人。
  2. 因爲1的視圖不需要知道主持人的存在。較少的依賴通常意味着更容易的維護

在C#中,我發現事件是將演示者與視圖分離的重要資產。更多的細節在以前的答案:Model-View-Presenter in WinForms

0
  1. 我會看MS棱鏡4,和他們不錯的導航界面。也看看Silverlight和WCF導航。他們做得很好,處理類似提示用戶從「髒」的形式確認,以消除東西。

  2. 我想看看WCF中的PageFunction()文檔,以及,對於如何「呼叫」從另一個頁面,並取回信息。

下面是它的工作原理(JavaScript的,不好意思):客戶名單上

用戶雙擊客戶:

CustomerList.onDblClick(customerId){ 

    app.fireEvent('customerEditRequest', id) 

} 

...

app.onCustomerEditRequest(id){ 
    this.mainRegion.requestNavigate('customers/edit', id); 
} 

如果導航編輯觀點是成功的......

CustomerEditView.onNavigatedTo(context){ 
    this.model.load(context.parameters.id)); 
} 

CustomerEditView.onSaveButtonClick(){ 
    this.model.save(); 
    app.fireEvent('customerEdited', id); 
} 

...

app.onCustomerEdited(id){ 
    app.mainRegion.requestNavigate('customerlist', id); 
} 

有幾種不同的方式,你可以這樣做:

  1. 發送的回調函數,編輯表格,從客戶名單。編輯表單會調用它,並在調用時做你想做的事情。

  2. 有你傾聽並做出反應(無應用範圍總線)上的「customerEdited」事件的編輯形式提高

  3. 使用的應用程序範圍內的事件總線集中管理的事件,顯示。

0

我曾經讓我的觀點與他們的主持人溝通,但已經離開了。這不符合一個模式(本身不是一個理由偏離只是一個因素,以確切的利益)的原始定義。理想情況下,視圖應該保持愚蠢,儘可能少的依賴關係。查看應溝通瓦特/演示者通過委託/事件/一些「射後不理」機制(任何「觀察家」)。事實上,我在MVP中引入了一個控制器,專門用於攔截View事件,並重新啓動演示者(很少)與演示者共享,或與系統或演示者特定事件總線通信 - 使我改變用戶行爲警報機制而不觸摸視圖。儘管如此,必須小心事件公共汽車。很快你就會開始拋出所有事件,應用程序在處理事件時會變得喋喋不休,事件並不是.NET中最快的事情。同步是一個額外的問題,尤其是如果你的應用程序需要與你的用戶進行更「對話」的交互。

應該記住,儘管Presenter是通過視圖/過程特定的,視圖(和視圖模型)可以被重用;將該視圖與Presenter進行遏制/委派關係強烈支持查看/限制其重用。這可以通過一些DI來減少,但是在大多數情況下我發現DI容器是不必要的複雜性(因爲我必須知道如何創建對象,以及在創建/測試它之後多久換一個對象換另一個語義相似的對象?)。具體的依賴不依賴除了另一層/增加更多的模糊/使事情更難以調試/跟蹤。儘管最近已經有了一個「簡單」的腳步,並且大多數人更喜歡在大多數應用程序的Factory/object創建/ ORM映射上進行操作,因爲通常使用「1對1」btw數據庫表/實體,並且需要添加一般的第三方ORM工具的複雜性,即使你理解它們是如何工作的(而不是重點),通過上下文/需要服務於不同應用程序的通用第三方ORM工具必須使事情變得比他們需要的更難。

此外,View在MVP中觀察模型(如在MVC中)仍然非常可行,所以我不會那麼快地排除這一點。我不喜歡自己做這件事,但它不會「打破」這種模式。事實上,我大約十年前開發了類似於MVP的東西,因爲我不喜歡MVC組件的「循環循環」(View about Model)。我更願意擁有清晰的分離btw View和Model,以表示所有這些模式(包括MVC)所聲稱的,以及希望保持View儘可能愚蠢(觀察模型woujld意味着需要更多的智能來處理模型更改)。我最終做的事情就像MVVM和策略模式,我使用模型的「子結構」傳遞給視圖,用作「更改通知器」。這使得一切都可以查看特定目的和靈活/可重複使用(艱難的組合)。

相關問題