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.Context
和cal:View.Model
– 我正在使用这些所有用户来切换可用的不同可用View
状态(该面板中显示的每个ViewModel
inheritance自所有具有State
属性的基本ViewModel
类)。
有几个地方我使用一些相同的Views
和ViewModels
弹出不同的窗口。 为此,我使用了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视图如下所示:
...
那么ResultsGraphView
和BenchmarkPickerView
都是这样的:
... ... ... 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方面,但它可能足以帮助你开始。