使用Caliburn.Micro MVVM WPF进行视图导航的建议 [英] Advice on Views navigation using Caliburn.Micro MVVM WPF

查看:122
本文介绍了使用Caliburn.Micro MVVM WPF进行视图导航的建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Caliburn Micro的新手,并希望获得一些建议,以采取哪些方式来开发我的应用程序界面和视图之间的导航. 我的想法是要有一个MainWindow,它将包含一个按钮菜单,每个按钮都与一个特定的视图相关.每个视图将存储在单独的WPF UserControl中. mainWindow还将包含一个TabControl,该控件绑定到viewmodel上选项卡的ObservableCollection上.每次单击菜单上的按钮时,我想添加一个带有ContentPresenter的新选项卡,该选项卡将动态加载视图及其对应的viewmodel.

I'm new on Caliburn Micro and want some advice on which path to take to devolop my app interface and navigation between views. My idea is to have a MainWindow which will contain a menu of buttons, each one related with a specific view. Each view will be stored in a separated WPF UserControl. The mainWindow will also contain a TabControl bound to an ObservableCollection of tabs on viewmodel. Everytime a button on menu is clicked, I want to add a new tab with a ContentPresenter inside that will dynamically load a view and its corresponding viewmodel.

所以我的问题:

1)我应该在这里使用屏幕集合吗?

1) Should I use a Screen Collection here?

2)UserControl应该实现Screen界面吗?

2) Should the UserControl implement Screen interface?

3)如何告诉MainWindow ViewModel在新添加的选项卡上加载哪个视图,以保持视图模型分离?

3) How do I tell MainWindow ViewModel which view to load on the new added tab maintaining viewmodels decoupled?

谢谢大家.

更新

经过大量阅读和社区的一些帮助后,我设法解决了这个问题.这是生成的AppViewModel:

After a lot of reading and some help of the community I managed to resolve this. This is the resultant AppViewModel:

class AppViewModel : Conductor<IScreen>.Collection.OneActive
{
    public void OpenTab(Type TipoVista)
    {
        bool bFound = false;
        Screen myScreen = (Screen)Activator.CreateInstance(TipoVista as Type);
        myScreen.DisplayName = myScreen.ToString();
        foreach(Screen miItem in Items)
        {
            if (miItem.ToString() == myScreen.ToString())
            {
                bFound = true;
                ActivateItem(miItem);
            }                
        }
        if (!bFound) ActivateItem(myScreen);        
    }

    public ObservableCollection<MenuItem> myMenu { get; set; }
    public ObservableCollection<LinksItem> myDirectLinks { get; set; }

    public ICommand OpenTabCommand
    {
        get
        {                
            return new RelayCommand(param => this.OpenTab((Type) param), null);
        }
    }       

    public AppViewModel()
    {
        OpenTab(typeof(ClientsViewModel));            
        MenuModel menu = new MenuModel();
        myMenu = menu.getMenu();
        myDirectLinks = menu.getLinks();
    }        

    public void CloseTab(Screen param)
    {            
        DeactivateItem(param, true);
    }    
}

我必须从OpenTabCommand中保留ICommand,因为Caliburn.micro的名称约定似乎无法在DataTemplate内部使用.希望它可以帮助其他人.感谢所有人

I have to keep the ICommand from OpenTabCommand because the name convention of Caliburn.micro doesn't seems to work inside DataTemplate. Hope it could help someone else. Thanks to all

推荐答案

我使用Caliburn.Micro做了非常相似的事情,并基于示例中包含的SimpleMDI示例进行了一些调整,以适应我的需求.需求.

I've done something very similar using Caliburn.Micro, and based it on the SimpleMDI example included with the examples, with a few tweaks to fit my needs.

就像示例中一样,我有一个主要的ShellViewModel:

Much like in the example, I had a main ShellViewModel:

public class ShellViewModel : Conductor<IScreen>.Collection.OneActive
{
}

以及包含TabControl-<TabControl x:Name="Items">的相应ShellView,并将其绑定到ConductorItems属性.

with a corresponding ShellView containing a TabControl - <TabControl x:Name="Items">, binding it to the Items property of the the Conductor.

在这种特殊情况下,我在ShellView上也有一个ContextMenu,绑定(使用Caliburn.Micro约定)到一系列实例化和Activated其他ViewModels的命令(通常使用相应的UserControl,使用Conductor上的ActivateItem方法.

In this particular case, I also had a ContextMenu on my ShellView, bound (using the Caliburn.Micro conventions), to a series of commands which instantiated and Activated various other ViewModels (usually with a corresponding UserControl, using the ActivateItem method on the Conductor.

public class YourViewModel: Conductor<IScreen>.Collection.OneActive
{
    // ...

    public void OpenItemBrowser()
    {
        // Create your new ViewModel instance here, or obtain existing instance.
        // ActivateItem(instance)
    }
}

在那种情况下,我不需要创建具有任何特定依赖项的ViewModels,也不需要从程序中的任何其他位置创建ViewModels.

In that case, I didn't require the ViewModels to be created with any particular dependency, or from any other locations in the program.

在其他时候,当我需要从应用程序中的其他位置触发ViewModel时,我已经使用Caliburn.Micro EventAggregator来发布自定义事件(例如OpenNewBrowser),可以通过类实现相应的接口(例如IHandle<OpenNewBrowser>),因此您的主ViewModel可以具有一个简单的Handle方法,该方法负责打开所需的View:

At other times, when I've needed to trigger ViewModel from elsewhere in the application, I've used the Caliburn.Micro EventAggregator to publish custom events (e.g. OpenNewBrowser), which can be handled by classes implementing the corresponding interface (e.g. IHandle<OpenNewBrowser>), so your main ViewModel could have a simple Handle method responsible for opening the required View:

public class YourViewModel: Conductor<IScreen>.Collection.OneActive, IHandle<OpenNewBrowser>
{
    // ...

    public void Handle(OpenNewBrowser myEvent)
    {
        // Create your new ViewModel instance here, or obtain existing instance.
        // ActivateItem(instance)
    }
}

本节文档可能会很有用,尤其是简单MDI"部分.

This section of the documentation will probably be useful, especially the Simple MDI section.

我在评论中提到的其他代码:

Additional code I mentioned in the comments:

有时,我会沿着这些方式使用通用方法,以确保如果我拥有特定类型屏幕的现有实例,请切换至该实例,否则,请创建一个新实例.

I sometimes use a generic method along these lines ensure that if I have an existing instance of a screen of a particular type, switch to it, or create a new instance if not.

public void ActivateOrOpen<T>() where T : Screen
{
    var currentItem = this.Items.FirstOrDefault(x => x.GetType() == typeof(T));

    if (currentItem != null)
    {
        ActivateItem(currentItem);
    }
    else
    {
        ActivateItem(Activator.CreateInstance<T>());
    }
}

使用方式:

public void OpenBrowser()
{
    this.ActivateOrOpen<BrowserViewModel>();
}

这篇关于使用Caliburn.Micro MVVM WPF进行视图导航的建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆