2015-10-05 86 views
0

我有一個與WPF和Prism相關的設計相關問題。我正在處理規則應用程序,我需要在TreeView控件中以分層方式顯示不同類型的規則(模型)。我已經將Model的每個實例都包裝在它們各自的ViewModel中並將其綁定到TreeView。下面我試圖描述層次結構只是爲了強調可以有多個相同類型的ViewModel,並根據它們的選擇我需要相應地顯示它們各自的視圖。通過在WPF Prism中注入特定的ViewModel導航到視圖

規則

---集團(GroupViewModel實例1)

------ X(XViewModel實例1)

---------ž (ZViewModel實例1)

------ X(XViewModel實例2)

---集團(GroupViewModel實例2)

------ Y(YViewModel實例1)

------ Z(ZViewModel實例2)

--------- X(XViewModel實例3 )

問題:

我需要一個機制來首先從TreeView中獲取所選擇的項目,然後用開放的導航到視圖模型的視圖(基於樹的項目選擇具有鬆散耦合)和飼料/注入在View中選擇ViewModel。 需要獲取選定ViewModel的代碼示例,隨ViewModel的注入一起導航到View?

目標:

我要找來處理在WPF這種情況與棱鏡保持鬆耦合的一些最佳實踐。

重要注意事項: TreeView顯示在一個區域中,內容是另一個區域的一部分,我正在使用MEF DI容器。

回答

1

1)假設「執行」是某種業務邏輯,那麼在模型類中使用它似乎是完全有效的。與驗證同上。事實上,這可能是一個給定的,因爲你正在尋找所有的業務邏輯和驗證在一個地方。然後,該模型可能(可能)在將來重新使用,例如,如果您決定在現有模型之上開發基於Web的系統。事實上,我前一段時間是once asked a similar question

就我個人而言,我認爲擁有一個「豐富」的模型類是很好的,包括實現INotifyPropertyChanged的屬性,使其「具有約束力」。這是完全可以接受的,因爲這個接口不在UI相關的框架名稱空間(System.ComponentModel)中。爲了方便起見,我甚至將ICommand屬性包含在我的模型中,儘管它取決於您是多少「純粹主義者」,模糊了模型定義和視圖模型之間的界限。這導致你的第二個問題 - 通過擁有這樣一個模型,它可以通過VM屬性公開模型直接綁定到視圖。

很多WPF開發人員似乎都編寫基本上是模型類的鏡像映像的VM類(包含所有與之相關的映射代碼),但包括諸如INPC屬性和ICommands之類的內容。這是我(個人)從未見過的大量開銷。同樣,關於如何使用模型和虛擬機,似乎有兩個「陣營」,可能在某種程度上取決於應用程序需要如何「分層」。這很大程度上取決於個人偏好,而且像許多開發人員的挑戰一樣,我認爲不存在正確或錯誤的方法。

關於3),是否要單擊TreeView中的項目,導致在應用程序中的其他位置顯示視圖?我假設你正在使用依賴注入框架? AFAIK棱鏡區域經理需要這一點,我不知道如何在沒有DI框架的情況下使用區域管理器。

首先,您需要定義在一個區域中顯示該視圖,例如: -

<ContentControl Regions:RegionManager.RegionName="MyRegionName" /> 

要顯示的區域的視圖使用棱鏡區域經理: -

_regionManager.RequestNavigate("MyViewName", "MyRegionName"); 

當您使用DI框架註冊視圖時,將分配視圖名稱,例如這是如何在溫莎城堡完成: -

Container.Register(Component.For<MyView>().ImplementedBy<MyView>().LifeStyle.Transient.Named("MyViewName")); 

希望這會讓你在你的路上。 Prism導航有很多,尤其是讓你的頭腦看到生命週期。另外,通過導航視圖的虛擬機來實現INavigationAware以便它可以對事件作出反應通常是有用的。被導航到/從。

編輯(基於OP編輯):

你還沒有說,該地區是在同一個視圖樹視圖。如果是這樣,那麼你可以在沒有棱鏡導航的情況下實現這一點。 「主」 VM(涉及到TreeView的觀點)可能使當前選定規則的虛擬機,你可以綁定到ContentControl中(當然是一個INotifyPropertyChanged的屬性!):

<ContentControl Content="{Binding SelectedRule}" /> 

然後,它只是一個案例該規則的虛擬機設置的DataTemplates: -

<DataTemplate DateType="{x:Type XRuleViewModel}"> 
    ... XAML ... 
</DataTemplate> 

由於TreeView的選擇變化,ContentControl中會結合相應的規則VM,以及相應的DataTemplate將呈現所需的內容。

如果區域在單獨的視圖中,那麼您將需要使用棱鏡導航。這裏的問題是你需要導航的視圖名稱,但是你的「主」(TreeView)虛擬機不知道視圖,只有規則虛擬機。一個簡單的選項可能是在規則虛擬機上擁有一個公開相關視圖名稱的屬性。如果您更喜歡純粹主義者,並且希望將這些知識保留在虛擬機之外,那麼您可以實現一種機制,將所有規則虛擬機與其相應的視圖名稱(例如,在應用程序啓動期間)一起註冊。這可以像Dictionary一樣簡單。在TreeView中選擇規則VM時,您只需查找在RequestNavigate()調用中使用的相應視圖名稱即可。

+0

感謝您的回答,但我仍然無法獲得積分。 3.我知道區域和導航到View使用相同的技術,但問題是,我如何指示我的視圖顯示基於TreeView選定項目的特定ViewModel。是的,我在棱鏡中使用MEF DI。 –

+0

@FSX,所以你想顯示一個特定的視圖,取決於你點擊了哪個treeview項目?這個視圖在哪裏出現 - 作爲與樹視圖相同的窗口內的內容,還是其他內容? –

+0

看到我上面編輯的問題更多的細節和澄清 –

1

@Andrew在正確的軌道上。首先,除非你的架構絕對需要它,否則不需要將模型包裝在ViewModel中。其中,我猜可能沒有。完成此任務的最簡單方法是使用InvokeCommandAction來響應所選項目更改事件。然後執行一個將導航到所需視圖的命令。使用選定的tem作爲參數來確定您要查找的視圖。在您導航時,您還可以使用NavigationParameters將所選項目作爲參數傳遞,並在目標上使用INavigationAware以便在OnNavigatedTo方法中獲取該參數。

相關問題