使用WPF和Caliburn.Micro在视图中添加多个视图

我正在尝试使用带有WPF的Caliburn.Micro学习。 如何在视图中添加多个视图?

     

另一个视图,带有viewmodel:MyControlViewModel

   ...   

如果我只是添加视图,它将不会检测到它具有具有适当名称的viewmodel。 我怎么能把它绑在上面呢?

我已尝试使用不同的bootstrappers并使用类似cal:Bind.Model =“path / classname / merge of the two”。 试图将其添加到主视图和usercontrol(MyControlView)。 我非常感谢有关此事的任何帮助。 我几乎被卡住了,我真的想用Caliburn.Micro 🙂

最好的问候,钻石鱼

编辑:我仍然无法让它工作,问题似乎是在引导程序或其他东西。 但只是为了澄清,这是我正在为testproject运行的代码。

MainView xaml:

     

MainViewModel代码:

 public partial class MainViewModel : PropertyChangedBase { } 

MyControlView xaml:

     

MyControlView代码:

 public class MyControlViewModel : PropertyChangedBase { public string MyProp { get { return "Working"; } } } 

错误的屏幕截图: http : //clip2net.com/s/1gtgt

我试过了

 cal:Bind.Model="Test.ViewModels.MyControlViewModel" 

同样。 还尝试了cal-reference:

 xmlns:cal="http://www.caliburnproject.org" 

我的项目http://clip2net.com/s/1gthM的屏幕截图

由于文档主要用于silverlight,有时用于Caliburn而不是CM,我可能已经错误地实现了bootstrapper。 对于这个测试项目,它就像这样:(在App.xaml中使用.xaml-change)

 public class BootStrapper : Bootstrapper { } 

请帮帮我吧! 好像这是我缺少的一些基本内容:)

编辑 – 新(更完整)答案如下:

好的,CM正在为你做很多事情,这都是为了让你的类和xaml为CM准备好找到它。 如上所述,我更喜欢将代码显式化,而不是依赖于框架的隐式代码假设。

因此,来自默认CM项目的Bootstrapper就好了。

 public class AppBootstrapper : Bootstrapper { // ... You shouldn't need to change much, if anything } 

“Bootstrapper”部分非常重要,它指示应用程序启动时哪个ViewModel是您的第一个或主屏幕。

 [Export(Typeof(MainViewModel))] public class MainViewModel : Screen, IShell { [ImportingConstructor] public MainViewModel(YourFirstViewModel firstViewModel, YourSecondViewModel secondviewModel) // etc, for each child ViewModel { } } 

[ImportingConstructor] ,除了指定MainViewModel需要存在其他ViewModel之外,您不需要执行任何操作。 在我的特定情况下,我喜欢我的MainViewModel是一个容器,只有容器,事件逻辑在别处处理。 但是你可以在这里轻松掌握你的Handle逻辑 – 但这是其他一些讨论。

现在每个子视图模型也需要自己导出,因此CM知道在哪里找到它们。

 [Export(Typeof(YourFirstViewModel))] public class YourFirstViewModel : IShell { // VM properties and events here } 

如果您只是使用默认构造函数,则无需指定导入构造函数。

现在,您对这些视图的每个视图都将如下所示:

        

XAMl或其中一个子视图

      

到底是怎么回事?

好吧,CM在引导程序中看到,由于指定public class AppBootstrapper : Bootstrapper的行,MainViewModel是起点。 MainViewModel要求在其构造函数中需要YourFirstViewModelYourSecondViewModel (以及其他ViewModel),因此CM构造每个。 所有这些ViewModel最终都会出现在IoC中(以后会让您的生活变得更轻松 – 再次,整个其他讨论)。

CM处理代表您为每个视图分配datacontext,因为您指定要绑定到哪个VM的行如cal:Bind.Model="Your.Namespace.ViewModels.YourFirstViewModel"

运气好的话,应该让你开始吧。 另请参阅CM示例项目Caliburn.Micro.HelloEventAggregator因为它完全符合您的要求(虽然,它被描述为事件聚合器演示,这也是非常有用的 – 但同样,另一个讨论)

(尊敬的原始答案,如下)

你需要这样做:

    

注意行cal:Bind.Model="Your.Namespace.Here.YourViewModel" ,它指定将此视图绑定到的确切视图模型。

不要忘记导出您的类类型,否则cm无法找到它。

 [Export(typeof(YourViewModel))] public class YourViewModel : IShell { ... } 

然后,您可以根据需要嵌套用户控件。 这是使用CM的一种非常好的方式,你会发现它具有高度可扩展性。 唯一的缺点是View和ViewModel必须在同一个项目中(据我所知)。 但是这种方法的优势在于,如果您愿意,可以将View和View Model类分离到不同的命名空间(在同一个项目中),以保持组织有序。

作为对cm的评论,我更喜欢这种方法,实际上,即使我不需要嵌套View UserControl等。 我宁愿明确地声明一个View被绑定的女巫VM(并且仍然允许CM处理IoC中所有繁重的工作),而不是让cm从隐含代码中“弄明白”。

即使有一个好的框架:显式代码比隐含代码更易于维护。 指定绑定的视图模型具有明确说明您的数据上下文预期的好处,因此您不需要稍后猜测。

更好的方法是在主视图上使用ContentControl ,并在MainViewModel为其提供与MyControlViewModel类型相同的公共属性。 例如

MainView.xaml

  

MainViewModel.cs

 // Constructor public MainViewModel() { // It would be better to use dependency injection here this.MyControlViewModel = new MyControlViewModel(); } public MyControlViewModel MyControlViewModel { get { return this.myControlViewModel; } set { this.myControlViewModel = value; this.NotifyOfPropertyChanged(...); } } 

在文件App.xaml.cs中,在方法GetInstance中添加以下行

 protected override object GetInstance(Type service, string key) { if (service == null && !string.IsNullOrWhiteSpace(key)) { service = Type.GetType(key); key = null; } // the rest of method }