Caliburn Micro – >从多个视图/ UserControls / CustomControls组合视图

如何在CM托管窗口中重用和组合部件? 我找到了关于使用两个UserControl来绑定到同一个ViewModel的post,但是如果我想在同一个窗口中创建多个视图和视图模型,那就没那么多了。 (每个视图的视图模型组成“主视图”)

我的问题的第一部分是如何分解组件以便重复使用? 如果我有一个窗口的两个区域,其中一个是数据网格,另一个是带有标签和文本框的详细信息视图,这些区域应该是单独的用户控件,自定义控件还是窗口? 理想情况下,每个人都可以独立,因此可以将它们分开并用于其他窗户。

因此,如果它们被分开,我最终会得到2个视图模型和2个视图。 现在假设我想创建3个窗口,一个窗口带有第一个视图,第二个带有第二个视图,第三个带有两个视图。 如何使用CM为每个视图创建窗口并将每个视图连接到其视图模型? 从我看到的例子中,我在窗口中看到了大部分视图和视图模型。

我想我以前做过类似于你所问的事情。 我一直在玩TabControl之一,打算为我喜欢的游戏托管几种不同的工具。

主要工具是类似于通常的文件浏览器类型程序的项目浏览器,类似于Jon上面描述的内容。 我将解释一些可能感兴趣/相关的部分(我已经删除了一些略显模糊的命名)。

主要的ExplorerView选项卡与Jon描述的完全相同(希望这是一个好兆头 – 意味着我不疯狂= D)

  >            

关联的ViewModel包含另外两个ViewModels ,用于组合主浏览器视图:

 public class ItemsTabViewModel : Conductor.Collection.AllActive { public ItemsViewModel ItemsExplorer { get; set; } public ExplorerPanelViewModel PanelView { get; set; } // Ctor etc. } 

ItemsExplorer托管TreeView样式控件,允许用户从游戏中探索各种类别的Item 。 这在应用程序的多个位置使用,并由几个不同的控件组成。

ExplorerPanelView是右侧的面板,根据用户正在查看的项目类型,它会更改为显示多个ViewModels 。 用户还可以选择在ExplorerPanelView显示的ViewModel上切换几个不同的Views

ExplorerPanelView看起来像:

      

而后面的ExplorerPanelViewModel

 public class ExplorerPanelViewModel : Conductor.Collection.OneActive, IHandle // More events. { public ItemViewModel ItemInfo { get; set; } public CategoryFolderViewModel CategoryFolderInfo { get; set; } public ExplorerPanelViewModel() { // My helper to access the `Caliburn.Micro` EventAggregator. EventAggregatorFactory.EventAggregator.Subscribe(this); // Other code } public void Handle(ItemSelectedEvent message) { // Other code to check active status ItemInfo = message.selected; ActivateItem(ItemInfo); } protected override void OnDeactivate(bool close) { Debug.WriteLine("Deactivated " + this.ToString() + close.ToString()); if (close) { EventAggregatorFactory.EventAggregator.Unsubscribe(this); } base.OnDeactivate(close); } // Other code } 

我试图删除很多不相关的代码。 基本上我再次托管多个ViewModels作为属性(虽然你可以拥有一个集合)并在我的ItemsExplorerViewModel引发ItemsExplorerViewModel事件时激活相关的ViewModel 。 我正在使用Caliburn.Micro EventAggregator来处理多个ViewModels之间的通信。

理论上,您可以省略属性,只需激活事件本身中引用的ViewModels

关于cal:View.Contextcal:View.Model – 我正在使用这些所有用户来切换可用的不同可用View状态(该面板中显示的每个ViewModelinheritance自所有具有State属性的基本ViewModel类)。

有几个地方我使用一些相同的ViewsViewModels弹出不同的窗口。 为此,我使用了Caliburn.Micro WindowManager 。 在官方文档中没有太多关于它(你最好搜索谷歌和CM的讨论),它在锡上说的很好。

如果您查看Caliburn.Micro.IWindowManager接口,您将看到一些可以从WindowManager实例调用的方便方法。

 public interface IWindowManager { bool? ShowDialog(object rootModel, object context = null, IDictionary settings = null); void ShowPopup(object rootModel, object context = null, IDictionary settings = null); void ShowWindow(object rootModel, object context = null, IDictionary settings = null); } 

因此,要使用您选择的ViewModel弹出一个新Window ,我在这些方面做了一些事情:

 // Some basic Window settings. dynamic settings = new ExpandoObject(); settings.Title = "Test Window"; settings.WindowStartupLocation = WindowStartupLocation.Manual; settings.SizeToContent = SizeToContent.Manual; settings.Width = 450; settings.Height = 300; var TestViewModel new TestViewModel(); WindowManagerFactory.WindowManager.ShowWindow(this.classSearch, null, settings); 

Caliburn.Micro应该再次将您的Views解析为正确的ViewModels

希望某处有一些有用的东西。 我通过一些设计迭代得出了这个解决方案,所以这可能不是解决其中一些问题的最佳方法。 如果有人有任何建设性的批评,请让我知道= D.

我不会以任何方式声称自己是CM的专家,但我已经用一个简单的“基准探险家”取得了合理的成功。 它使用单个“shell视图”组成另外两个视图,每个视图都有自己的ViewModel。 shell视图如下所示:

   ...      

那么ResultsGraphViewBenchmarkPickerView都是这样的:

   ... ... ... controls ...   

ShellViewModel将其他两个ViewModel公开为属性。 然后在构造时自动将它们传递给视图。 (引导程序没有提供任何获取它们的方法。)

现在这不太适合你的描述,因为我不认为你可以单独使用两个单独的视图作为窗口 – 我怀疑你最终会得到5个视图:

 SubViewOne - a UserControl with the first view parts SubViewTwo - a UserControl with the second view parts JustViewOne - a Window containing just SubViewOne JustViewTwo - a Window containing just SubViewTwo BothViews - a Window containing both SubViewOne and SubViewTwo 

认为没有办法绕过这样一个事实:你不希望另一个Window 另一个Window ,而顶层窗口必须是……好吧,一个Window

希望这会有所帮助,如果你想了解我正在做的小项目的更多细节,请告诉我 – 它远没有生产质量,特别是在DI方面,但它可能足以帮助你开始。