我想创建一个灵活的应用程序,它是ViewModel驱动的。
基本流程是这样的:
如果需要显示子视图模型,则通过DataTemplate完成。
这种方法也可以看作here(选项8)。
所以主窗口xaml看起来像这样:
<Window>
<!-- somehow I need to add the mapping from ViewModel to View -->
<Grid>
<!-- the main ViewModel -->
<ContentPresenter Content="{Binding Path=Content}"/>
</Grid>
</Window>
Content
属性可能包含一个视图模型,其中包含名为Children
的元素列表,并且它的关联DataTemplate可能如下所示:
孩子们也可以通过合适的DataTemplate灵活地呈现。
<UserControl>
<Grid>
<StackPanel>
<!-- display the child ViewModels in a list -->
<ItemsControl ItemsSource="{Binding Path=Children}" />
</StackPanel>
</Grid>
</UserControl>
我应该如何组织ViewModel,Views及其DataTemplates,以便我不需要在MainWindow中对它们进行硬连线处理?
如何将其连接到主窗口?
如果它是可存根的,那就太好了,即我可以在设计时使用设计时dataContext看到结果。
基本上我想捆绑View,ViewModel和DataTemplate,并且能够在不需要了解细节的应用程序中使用它们(例如,一些子ViewModel实现某个接口并注入到主ViewModel中)
答案 0 :(得分:2)
你有没有看过Prism。
该框架允许您在UI中定义可以注册视图的区域。我相信这回答了你的第二个问题(2)。
xmlns:cal="http://www.codeplex.com/prism"
<Window>
<!-- somehow I need to add the mapping from ViewModel to View -->
<Grid>
<!-- the main ViewModel -->
<ContentPresenter cal:RegionManager.RegionName="MainRegion"/>
</Grid>
</Window>
对于您的第一个问题(1),我们按以下方式构建实体:
查看 - 我们有一个看起来相似的抽象基类:
public abstract class ViewBase<T> : UserControl, IView<T> where T: IViewModel
{
public T ViewModel
{
get
{
return this.viewModel;
}
protected set
{
this.viewModel = value;
this.DataContext = this.viewModel;
}
}
public ViewBase(IUnityContainer container)
{
this.ViewModel = container.Resolve<T>();
}
}
然后,我们可以使用以下命令在xaml中创建视图:
<ui:ViewBase x:Class="MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:ui="NAMESPACE FOR VIEWBASE"
xmlns:vm="NAMESPACE FOR VIEWMODEL"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:TypeArguments="vm:MYVIEWMODEL">
在View背后的代码中,我们执行以下操作:
public partial class MyView : ViewBase<IMyViewModel>
然后利用基类中的构造函数来解析ViewModel并将其设置为它的DataContext。
然后,您可以按预期设计视图(3),并且无需使用DataTemplate。
使用UnityContainer,我们按如下方式注册视图:
this.container.RegisterType<IMyView, MyView>();
this.container.RegisterType<IMyViewModel, MyViewModel>();
this.regionManager.RegisterViewWithRegion("MainRegion", typeof(IMyView));
请注意&#34; MainRegion&#34;这里匹配MainWindow xaml中指定的RegionName。如果要在同一区域中显示多个视图,或者甚至将MainWindow分解为不同的区域,可以进一步扩展它以使用TabControl。
我希望这会有所帮助。
答案 1 :(得分:0)
1)您可以在每个视图中添加UserControl.Resources中的DataTemplates,即
<UserControl.Resources>
<DataTemplate DataType="{x:Type viewmodels:Customer1ViewModel}">
<views:Customer1View/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:Customer2ViewModel}">
<views:Customer2View/>
</DataTemplate>
</UserControl.Resources>
现在您为每个ViewModel定义了相应的View。 您只为该视图中的ViewModel添加了数据模板, 即儿童的ViewModels
2)Hm,你的MainWindow也必须有一个ViewModel,即在MainWindow DataContext中放入一个MainWindows的ViewModel实例。 ViewModel必须包含属性Content(在其中放置ViewModel作为内容)。 您可以在App.xaml.cs中手动执行此操作
public partial class App : Application
{
public App()
{
this.Startup += App_Startup;
}
public void App_Startup(object sender, StartupEventArgs e)
{
this.MainWindow = new MainWindow();
//create view model and set data context
MainWindowViewModel vm = new MainWindowViewModel();
this.MainWindow.DataContext = vm;
//show window
this.MainWindow.ShowDialog(vm);
}
}
3)我不确定这一点,你可能无法在设计时看到结果。
我不确定我是否完全理解你想要什么,如果这没有帮助, 请重播这个答案并作进一步解释。