2012-02-20 66 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类用于相同的目的。