使用 viewmodel 命令打开新选项卡

发布于 2025-01-07 05:07:32 字数 385 浏览 1 评论 0原文

我有一个应用程序,其中有一个主视图模型,其视图包含一个选项卡控件,其中每个选项卡都有自己的视图和视图模型(可能还有更多)。我相信这是一个非常常见的设计。现在,我想通过从这些选项卡内的控件触发命令来打开新选项卡(通过实例化新视图模型并将它们添加到工作区集合中)。问题在于该命令是由控制选项卡的内部视图模型接收的,而不是由控制选项卡控件的外部视图模型接收的。这样做的最佳实践是什么?我能想到的所有解决方案都有点“hacky”(为视图模型提供对其父视图模型的引用,从父级订阅子级事件......)。我假设对此有一个很好的解决方案。

例如,从“实体列表”视图中,单击“新建”按钮或选择一行应打开另一个具有“实体详细信息”类型视图的选项卡。但是,该命令将由选项卡绑定到的“实体列表”视图的视图模型接收,而不是选项卡控件绑定到的“工作区列表”视图模型。

I have an application where I have a main viewmodel whose view contains a tabcontrol, where each tab has its own view and viewmodel (and possibly more of them). I believe this is a pretty common design. Now, I want to open new tabs (by instantiating new viewmodels and adding them to the collection of workspaces) by firing commands from controls inside those tabs. The problem is that the command is received by the inner viewmodel, that controls the tab, not the outer one that controls the tabcontrol. What would be the best practice to do this? All the solutions I can think of are kind of "hacky" (giving the viewmodel a reference to its parent viewmodel, subscribing to a child's event from the parent...). I am assuming there is a nice solution for this.

For example, from a "list of entities" view, clicking the "new" button or selecting a row should open another tab with an "entity details" type of view. However, the command will be received by the "list of entities" view's viewmodel, to whom the tab is bound, and not the "list of workspaces" viewmodel to whom the tabcontrol is bound.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

九公里浅绿 2025-01-14 05:07:32

一种可能性是让外部视图模型公开一个命令来创建新选项卡。我们使用集中式 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);
    }
}

One possibility is to have your outer viewmodel expose a command to create a new tab. We use a centralized CommandService, which is simply a dictionary of name-to-ICommand, which allows for decoupled global commands. Something like this:

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);
    }
}
椒妓 2025-01-14 05:07:32

您可以使用标准 .NET 事件(订阅父事件中的子事件),或者为了实现更多解耦,请使用事件聚合器模式。

PrismCaliburn.Micro 实现了事件聚合器模式,MVVM Light Toolkit 提供了出于相同目的的 Messenger 类。

You can use either standard .NET events (subscribing to the child events in the parent), or for more decoupling, use an event aggregator pattern.

Frameworks such as Prism and Caliburn.Micro implement the event aggregator pattern, and the MVVM Light Toolkit provides a Messenger class for the same purpose.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文