繁体   English   中英

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

[英]Advice on Views navigation using Caliburn.Micro MVVM WPF

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

所以我的问题是:

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

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

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

预先感谢大家。

UPDATE

经过大量阅读和社区的一些帮助后,我设法解决了这个问题。 这是生成的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中使用。 希望它可以帮助别人。 谢谢大家

我使用Caliburn.Micro进行了非常相似的操作,并基于示例附带的SimpleMDI示例进行了一些调整以满足我的需求。

与示例类似,我有一个主要的ShellViewModel

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

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

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

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

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

在那种情况下,我不需要使用任何特定的依赖关系或从程序中的任何其他位置创建ViewModels

在其他时候,当我需要从应用程序中的其他地方触发ViewModel ,我使用了Caliburn.Micro EventAggregator来发布自定义事件(例如OpenNewBrowser ),可以通过实现相应接口的类(例如IHandle<OpenNewBrowser> ),因此您的主ViewModel可以具有一个简单的Handle方法来负责打开所需的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”部分。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM