【问题标题】:MVVM Binding Views to TabControlItems - Views don't displayMVVM 将视图绑定到 TabControlItems - 视图不显示
【发布时间】:2016-06-02 20:51:58
【问题描述】:

我想在我的 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() });  
}

EDIT 然后显示在我的视图中:

<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。

我真的不明白我在这里想念什么!谢谢你的帮助。

【问题讨论】:

  • 编辑后的代码有效。

标签: c# wpf mvvm binding tabcontrol


【解决方案1】:

问题是每个选项卡都绑定到TabItem 的一个实例。您有 vm:ExportViewModelvm:ImportViewModel 的数据模板。你现在看到你的错误了吗?

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

另一种选择是为TabItem 添加一个DataTemplate,在其中粘贴一个ContentControl,然后将that 绑定到视图模型。下面是一些类似 xaml 的伪代码来说明这个想法:

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

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

第三个​​ 选项是实现自定义DataTemplateSelector 并在您的Tab 控件中使用that。在此选择器中,只需打开 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}>

【讨论】:

  • 非常感谢您的回答,我在实例化TabItems 时猜到了类似的事情,但目前仍然有点阴沉,您能准确一点吗?我会仔细研究您的第一个和第二个解决方案,如果可行,我将进行编辑。对于第三种解决方案,您是否有更多解释或示例? - 谢谢队友
  • @RizzCandy 默认的 DataTemplateSelector 查看绑定中对象的类型,然后在可视化树中查找其 DataType 属性与此类型匹配的 DataTemplate。它对您的 TabItem 或其 Content 属性一无所知。添加了一些 c# 和 xaml 之类的伪代码,可以指导您。
  • 非常感谢,但我尝试了许多解决方案都没有成功并得出了这个结论:当我使用 MVVM Light 时,我的 TabItem 属性ViewModelBase 是未定义的,即使我有 ViewModel我的 TabItem 集合。所以当在视图中调用 Content 时,它不知道要显示什么。目前我不知道如何解决这个问题!
  • 你说得对,我只是缺少DataTemplate.RessourcesContentControl 的语法。完美运行。我已经编辑了我的代码以使用正确的语法。我将保留您的第三个解决方案作为另一个案例的资产,因为它看起来非常有趣。
  • 我碰巧发现自己回到了数据模板选择器链帮派,据我所知,我的示例实现绝对行不通。 DataTemplateSelector 的基本实现确实很糟糕。现在我必须深入挖掘所有内容并找到我之前所做的事情:(
猜你喜欢
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
  • 2011-01-31
  • 2011-10-07
  • 1970-01-01
  • 2011-09-30
相关资源
最近更新 更多