使用Caliburn.Micro MVVM WPF建议视图导航

时间:2014-04-21 18:25:13

标签: c# wpf mvvm caliburn.micro

我是Caliburn Micro的新手,想要了解我的应用程序界面和视图之间导航的路径。 我的想法是有一个MainWindow,它将包含一个按钮菜单,每个按钮都与一个特定的视图相关。每个视图都将存储在单独的WPF UserControl中。 mainWindow还将包含一个TabControl,该TabControl绑定到viewmodel上的ObservableCollection选项卡。每次单击菜单上的按钮时,我想添加一个内部有ContentPresenter的新选项卡,它将动态加载视图及其相应的视图模型。

所以我的问题:

  

1)我应该在这里使用屏幕收藏吗?

     

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

     

3)如何告诉MainWindow ViewModel在新添加的选项卡上加载哪个视图,保持viewmodels解耦?

提前感谢所有人。

更新

经过大量的阅读和社区的帮助,我设法解决了这个问题。这是结果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);
    }    
}

我必须保持ICommand不受OpenTabCommand的影响,因为Caliburn.micro的名称约定似乎不适用于DataTemplate。希望它可以帮助别人。感谢所有

1 个答案:

答案 0 :(得分:3)

我使用Caliburn.Micro完成了类似的操作,并基于示例中包含的SimpleMDI示例,并根据我的需要进行了一些调整。

在示例中,我有一个主ShellViewModel

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

使用包含ShellView - TabControl的相应<TabControl x:Name="Items">,将其绑定到Items的{​​{1}}属性。

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

Conductor

在这种情况下,我不需要使用任何特定的依赖关系创建public class YourViewModel: Conductor<IScreen>.Collection.OneActive { // ... public void OpenItemBrowser() { // Create your new ViewModel instance here, or obtain existing instance. // ActivateItem(instance) } } ,也不需要从程序中的任何其他位置创建。{/ p>

在其他时候,当我需要从应用程序的其他位置触发ViewModels时,我已使用ViewModel Caliburn.Micro发布自定义事件(例如{{1} }),可以由实现相应接口的类(例如EventAggregator)处理,因此您的主OpenNewBrowser可以有一个简单的IHandle<OpenNewBrowser>方法负责打开所需的ViewModel

Handle

This section文档可能会有用,尤其是Simple MDI部分。

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

我有时会沿着这些行使用泛型方法,确保如果我有特定类型屏幕的现有实例,请切换到它,或者如果没有则创建新实例。

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)
    }
}