Caliburn.Micro 是 MIX10 讨论的最终结果,它自动将 ContentControl
s 绑定到已解析的视图和视图模型
您可以遵循相同的方法:
使子 VM 成为父 VM 的属性...(正如有人已经回答的那样)
public class UserViewModel
{
public User User { get; set; }
}
public class FeedbackViewModel
{
public UserViewModel UserView { get; set; }
}
然后使用ContentControl
允许子VM被注入到父视图中:
<UserControl x:Name="ParentView">
<StackPanel>
<TextBlock>Some Parent View Content here...</TextBlock>
<!-- Now the child content: -->
<ContentControl x:Name="UserView" />
</StackPanel>
</UserControl>
我假设由于您的框架基于 Rob 的原始演讲,它会根据约定自动绑定属性吗?如果是这样,这里采用相同的方法。ContentControl
从文档中可以看出,for 的约定与其他约定略有不同:
ContentControl 的约定有点有趣。如果我们绑定的项目不是值类型也不是字符串,那么我们假设 Content 是 ViewModel。因此,我们实际上没有像在其他情况下那样绑定到 Content 属性,而是使用 CM 的自定义附加属性:View.Model 设置绑定。此属性使 CM 的 ViewLocator 为视图模型查找适当的视图,并使 CM 的 ViewModelBinder 将两者绑定在一起。完成后,我们将视图弹出到 ContentControl 的 Content 属性中。这个单一的约定使得框架中强大而简单的 ViewModel-First 组合成为可能。
这个约定的代码是:
AddElementConvention<ContentControl>(ContentControl.ContentProperty, "DataContext", "Loaded").GetBindableProperty =
delegate(DependencyObject foundControl)
{
var element = (ContentControl)foundControl;
if (element.Content is DependencyObject && !OverwriteContent)
return null;
#if SILVERLIGHT
var useViewModel = element.ContentTemplate == null;
#else
var useViewModel = element.ContentTemplate == null && element.ContentTemplateSelector == null;
#endif
if (useViewModel) {
Log.Info("ViewModel bound on {0}.", element.Name);
return View.ModelProperty;
}
Log.Info("Content bound on {0}. Template or content was present.", element.Name);
return ContentControl.ContentProperty;
};
如您所见,检查Content
/ContentTemplate
以查看它是否是可视元素,如果不是,则假定它是 VM。然后,可绑定属性作为 VM 本身(在未设置内容模板的情况下)或内容本身返回。
可能值得一读以获得更多想法:
http://caliburnmicro.codeplex.com/wikipage?title=Screens%2c%20Conductors%20and%20Composition&referringTitle=Documentation
(滚动到准导体部分)
至于在您的应用程序中执行此操作以Users
替换为 ViewModels - 我认为这只是通过它的一个案例
您可以使用视图优先的方法,并可能在解析 VM 时通过工厂将数据上下文转换为 VM,但它只会变得一团糟!(除非绝对必要,否则我不太喜欢混合 View-First 和 ViewModel-First 方法的想法)