没有ItemsSource的TabControl ItemTemplate

时间:2012-03-06 22:13:57

标签: wpf data-binding mvvm tabs

我正在使用TabControl进行WPF应用程序。一开始我有一个TabControl绑定到TabBase项的ObservableCollection,其中TabBase是tab viewmodel的基类:

<TabControl
    IsSynchronizedWithCurrentItem="True"
    ItemsSource="{Binding Tabs}"
    ItemTemplate="{StaticResource ClosableTabTemplate}"
...
public ObservableCollection<TabBase> Tabs { get; private set; }
...
public abstract class TabBase : ViewModelBase
...
public abstract class ViewModelBase : INotifyPropertyChanged
{
    public virtual string DisplayName { get; protected set; }
...
<DataTemplate x:Key="ClosableTabTemplate">
    <DockPanel Width="120">
        <Button
            Command="{Binding Path=CmdClose}"
            Content="X"
            />
        <ContentPresenter 
            Content="{Binding Path=DisplayName}">
        </ContentPresenter>
    </DockPanel>
</DataTemplate>

但是当我切换标签时,我遇到了一个问题,看起来每次创建当前标签,即使它之前已经打开过。通过StackOverflow搜索我找到了解决方案here,并参考了here。我已经用声明的ItemsSource代替了代码中动态创建选项卡。选项卡切换性能问题已得到解决,但是标签标题已丢失了与模板的链接,因此我没有看到任何标题标题标题,而是使用标题和关闭按钮。使用制表符创建代码,我能够恢复标签大小和关闭按钮,但没有绑定 - 没有标题和关闭按钮不起作用(5行与item.Header恢复原始标签大小):

    private void AddTabItem(TabBase view)
    {
        TabItem item = new TabItem();
        item.DataContext = view;
        item.Content = new ContentControl();
        (item.Content as ContentControl).Focusable = false;
        (item.Content as ContentControl).SetBinding(ContentControl.ContentProperty, new Binding());

        item.Header = new ContentControl();
        (item.Header as ContentControl).DataContext = view;
        (item.Header as ContentControl).Focusable = false;
        (item.Header as ContentControl).SetBinding(ContentControl.ContentProperty, new Binding());
        item.HeaderTemplate = (DataTemplate)FindResource("ClosableTabTemplate");

        tabControl.Items.Add(item);
    }

问题是,如何在没有ItemsSource绑定的情况下让ItemTemplate为TabControl工作?

1 个答案:

答案 0 :(得分:2)

当您将item.Header显式设置为ContentControl时,HeaderTemplate现在将该对象用作其DataContext。通常,Header属性将获取ViewModel,ContentPresenter将获取该(非Visual)对象并将HeaderTemplate应用于它。您现在已将ViewModel推送到层次结构中的某个级别,因此模板未应用于与数据相同的位置。移动任何一个应该修复Binding问题,但是一个或另一个可能更适合您的情况:

item.Header = view;

(item.Header as ContentControl).ContentTemplate = (DataTemplate)FindResource("ClosableTabTemplate");