2012-02-20 60 views
1

我有一個應用程序,其中我有一個主視圖模型的視圖包含一個tabcontrol,其中每個選項卡都有自己的視圖和viewmodel(可能更多)。我相信這是一個很常見的設計。現在,我想打開新的標籤(通過實例化新的視圖模型並將它們添加到工作空間的集合中),方法是從這些標籤中的控件觸發命令。問題在於命令由內部視圖模型接收,該內部視圖模型控制選項卡,而不是控制選項卡控件的外部視圖模型。最佳做法是什麼?我能想到的所有解決方案都有點「黑客」(給viewmodel一個對其父視圖模型的引用,從父級訂閱一個孩子的事件...)。我假設有一個很好的解決方案。使用viewmodel命令打開新標籤

例如,從「實體列表」視圖中,單擊「新建」按鈕或選擇一行應打開具有「實體詳細信息」類型的視圖的另一個選項卡。但是,該命令將被「實體列表」視圖的視圖模型接收,該視圖模型綁定了該選項卡,而不是綁定tabcontrol的「工作空間列表」視圖模型。

回答

1

一種可能性是讓您的外部視圖模型公開一個命令來創建一個新選項卡。我們使用一個集中的CommandService,它只是一個名稱到ICommand的字典,它允許解耦的全局命令。就像這樣:

public interface ICommandService 
{ 
    void RegisterCommand(string name, ICommand command); 
    ICommand this[string name] {get;} 
} 

public class OuterViewModel 
{ 
    public OuterViewModel (ICommandService commandService) 
    { 
     commandService.RegisterCommand("OpenNewTab", OpenNewTab); 
    } 

    private void OpenNewTab (object newTabViewModel) 
    { 
     // The new tab's viewmodel is sent as the ICommand's CommandParameter 
    } 
} 

public class InnerViewModel 
{ 
    public InnerViewModel (ICommandService commandService) 
    { 
     _commandService = commandService; // Save injected service locally. 
    } 

    public HandleClickOnInnerTabpage() 
    { 
     AnotherViewModel newVM = new AnotherViewModel(...); 
     _commandService["OpenNewTab"].Execute(newVM); 
    } 
} 
+0

我決定使用類似的東西。我有一個單身的ServiceRegister,一個對象可以註冊自己作爲某種類型的服務。所以作爲tabcontrol的綁定的viewmodel確實......註冊(this)。內部視圖模型執行GetServices ()。 IOpenWorkspaces接口包含一個方法,一個參數化的OpenWorkspace。 – svinja 2012-02-22 13:38:49

1

您可以使用標準的.NET事件(訂閱父級中的子事件),或者爲了更多的解耦,可以使用事件聚合器模式。

框架如PrismCaliburn.Micro實現事件聚合器模式,並且MVVM Light Toolkit提供一個Messenger類用於相同的目的。