如何将TabControl绑定到ViewModel的集合?

基本上我有我的MainViewModel.cs中:

ObservableCollection<TabItem> MyTabs { get; private set; } 

不过,我需要以某种方式不仅能够创build标签,而且还要在保持MVVM的同时将标签内容加载并链接到相应的视图模型。

基本上,我怎样才能得到一个用户控件作为tabitem的内容加载,并有该用户控件连线到适当的视图模型。 造成这个困难的部分是ViewModel不应该构造实际的视图项目,对吧? 或者可以吗?

基本上,这是MVVM是否合适:

 UserControl address = new AddressControl(); NotificationObject vm = new AddressViewModel(); address.DataContext = vm; MyTabs[0] = new TabItem() { Content = address; } 

我只问,因为好,我构build一个ViewModel中的视图(地址控制),这对我来说听起来像一个MVVM no-no。

这不是MVVM。 您不应该在视图模型中创buildUI元素。

您应该将Tab的ItemsSource绑定到ObservableCollection,并且应该包含关于应该创build的选项卡信息的模型。

这里是虚拟机和代表一个标签页的模型:

 public sealed class ViewModel { public ObservableCollection<TabItem> Tabs {get;set;} public ViewModel() { Tabs = new ObservableCollection<TabItem>(); Tabs.Add(new TabItem { Header = "One", Content = "One's content" }); Tabs.Add(new TabItem { Header = "Two", Content = "Two's content" }); } } public sealed class TabItem { public string Header { get; set; } public string Content { get; set; } } 

这里是绑定窗口的外观:

 <Window x:Class="WpfApplication12.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Window.DataContext> <ViewModel xmlns="clr-namespace:WpfApplication12" /> </Window.DataContext> <TabControl ItemsSource="{Binding Tabs}"> <TabControl.ItemTemplate> <!-- this is the header template--> <DataTemplate> <TextBlock Text="{Binding Header}" /> </DataTemplate> </TabControl.ItemTemplate> <TabControl.ContentTemplate> <!-- this is the body of the TabItem template--> <DataTemplate> <TextBlock Text="{Binding Content}" /> </DataTemplate> </TabControl.ContentTemplate> </TabControl> </Window> 

呵呵,一个UserControl:

 <TabControl ItemsSource="{Binding Tabs}"> <TabControl.ItemTemplate> <!-- this is the header template--> <DataTemplate> <TextBlock Text="{Binding Header}" /> </DataTemplate> </TabControl.ItemTemplate> <TabControl.ContentTemplate> <!-- this is the body of the TabItem template--> <DataTemplate> <MyUserControl xmlns="clr-namespace:WpfApplication12" /> </DataTemplate> </TabControl.ContentTemplate> </TabControl> 

在Prism中,您通常会将选项卡控件设置为区域,以便您不必控制绑定的选项卡页面集合。

 <TabControl x:Name="MainRegionHost" Regions:RegionManager.RegionName="MainRegion" /> 

现在可以通过注册自己到区域MainRegion添加视图:

 RegionManager.RegisterViewWithRegion( "MainRegion", ( ) => Container.Resolve<IMyViewModel>( ).View ); 

在这里你可以看到棱镜的特长。 视图由ViewModel实例化。 在我的情况下,我通过控制反转容器(例如Unity或MEF)来parsingViewModel。 ViewModel通过构造函数注入获取视图,并将其自身设置为视图的数据上下文。

另一种方法是将视图的types注册到区域控制器中:

 RegionManager.RegisterViewWithRegion( "MainRegion", typeof( MyView ) ); 

使用这种方法,您可以在运行时后期(例如通过控制器)创build视图:

 IRegion region = this._regionManager.Regions["MainRegion"]; object mainView = region.GetView( MainViewName ); if ( mainView == null ) { var view = _container.ResolveSessionRelatedView<MainView>( ); region.Add( view, MainViewName ); } 

由于您已经注册了视图的types,视图被放置在正确的区域。

我有一个转换器来解耦UI和ViewModel,即下面的点:

 <TabControl.ContentTemplate> <DataTemplate> <ContentPresenter Content="{Binding Tab,Converter={StaticResource TabItemConverter}"/> </DataTemplate> </TabControl.ContentTemplate> 

Tab是我的TabItemViewModel中的一个枚举,而TabItemConverter将它转换为真实的UI。

在TabItemConverter中,只需获取您需要的值并返回一个usercontrol。