我正在使用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工作?
答案 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");