MVVM绑定视图到TabControlItems - 视图不显示

时间:2016-05-19 16:04:25

标签: c# wpf mvvm binding tabcontrol

我想在我的MainView中的TabControlItems中显示不同的视图。

要做到这一点,我创建了一个这样的类:

public sealed class TabItem
{
    public string Header { get; set; }
    public ViewModelBase Content { get; set; }
}

我在我的ViewModel中调用List

private ObservableCollection<TabItem> _views;
public ObservableCollection<TabItem> Views
{
    get { return _views; }
    set
    {
        _views = value;
        RaisePropertyChanged(() => Views);
    }
}

public IndexMainViewModel()
{
    Views = new ObservableCollection<TabItem>();
    Views.Add(new TabItem { Header = "Export", Content = new ExportViewModel() });
    Views.Add(new TabItem { Header = "Import", Content = new ImportViewModel() });  
}

编辑然后在我的视图中显示:

<window xmlns:views="clr-namespace:EDICOT_Module_Import_Export_Articles.View"
xmlns:vm="clr-namespace:EDICOT_Module_Import_Export_Articles.ViewModel"
xmlns:model="clr-namespace:EDICOT_Module_Import_Export_Articles.Model.Classes"
DataContext="{Binding IndexMainVM, Source={StaticResource Locator}}">

   <TabControl ItemsSource="{Binding Views}">
    <TabControl.Resources>
        <DataTemplate DataType="{x:Type model:TabItem}">
            <DataTemplate.Resources>
                <DataTemplate DataType="{x:Type vm:ImportViewModel}">
                    <views:ImportView />
                </DataTemplate>
                <DataTemplate DataType="{x:Type vm:ExportViewModel}">
                    <views:ExportView />
                </DataTemplate>
            </DataTemplate.Resources>
            <ContentControl Content="{Binding Content}"/>
        </DataTemplate>
    </TabControl.Resources>

    <TabControl.ItemTemplate >
        <DataTemplate >
            <TextBlock Text="{Binding Header}"/>
        </DataTemplate>
    </TabControl.ItemTemplate>
</TabControl>

问题是它只显示标题但不显示内容(视图),而是显示TabItem类的路径。

要提供更多信息:我已经截断了代码以仅保留主题所需的内容并使用MVVM Light。

我真的没有得到我想念的东西!谢谢你的帮助。

1 个答案:

答案 0 :(得分:2)

问题是每个标签都绑定到TabItem的实例。您有vm:ExportViewModelvm:ImportViewModel的DataTemplates。你现在看到错误吗?

有很多解决方案。最简单的方法是将Header文本移动到基本视图模型中,并将该Tab控件绑定到ViewModel集合。

另一种方法是为TabItem添加DataTemplate,在其中粘贴ContentControl,并将 绑定到视图模型。这里有一些类似xaml的伪代码来说明这个想法:

<DataTemplate DataType="{x:Type vm:TabItem}">
    <ContentControl Content={Binding Content}" />
</DataTemplate>

您可能必须将视图模型的模板移动到ContentControl的资源中,但我认为这不是必需的。您可能需要调整TabItem数据模板,以便它也填充选项卡窗口。

第三个​​ 选项是实现自定义DataTemplateSelector并在Tab控件中使用 。在这个选择器中,只需破解你的TabItem并查看该类型的Content属性。您可以浏览默认DataTemplateSelector的源代码,以了解如何获取给定类型的正确模板。这种方法让你深入了解WPF,这是一次有趣的旅行。 我已经完成了一次,我宁愿不再这样做了。 实际上,根据您的需要,旅行不会像我的那样糟糕。默认选择器不下蹲,所以返回base.SelectTemplate毫无价值。我在框架中挖掘了一个如何实现它的例子。

public class TabItemDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate
        SelectTemplate(object item, DependencyObject container)
    {
        var viewModel = item as TabItem;
        if (item == null)
            return null;
        else
            item = viewModel.Content;

        FrameworkElement fe = null;
        if (container is ContentPresenter)
            fe = (container as ContentPresenter)
                    .TemplatedParent as FrameworkElement;
        else
            fe = container as FrameworkElement;

        var key = new DataTemplateKey(item.GetType());
        return fe.TryFindResource(key) as DataTemplate;
    }
}

将其实例添加到资源某处

<derp:TabItemDataTemplateSelector x:Key="tidts"/>

然后将其绑定到ContentTemplateSelector

<TabControl ItemsSource="{Binding Views}"
            ContentTemplateSelector={StaticResource tidts}>