什么是TabControl.ItemTemplate的DataContext?

时间:2012-02-13 21:54:28

标签: .net wpf datatemplate

鉴于以下XAML:

<TabControl DataContext="{StaticResource mainVM}" ItemsSource="{Binding MovableVM.Docked, UpdateSourceTrigger=PropertyChanged}">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock>
                    <TextBlock Text="{Binding ContentTitle}"/>
                </TextBlock>
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ContentTemplate>
            <DataTemplate>
                <ContentPresenter Content="{Binding}"/>
            </DataTemplate>
        </TabControl.ContentTemplate>
</TabControl>

我希望两个DataTemplate具有相同的DataContext,其预期结果是ItemsSource中的实际项目(实现IMovable接口的UserControl,见下文)显示在单独的选项卡和每个选项卡的标题,以显示同一项目的属性ContentTitle的内容。

IMovable对象 按预期显示,但与ContentTitle的绑定正在为标头工作。如果我更改ContentTemplate中的绑定,就像这样......

<TabControl.ContentTemplate>
    <DataTemplate>
        <ContentPresenter Content="{Binding ContentTitle}"/>
    </DataTemplate>
</TabControl.ContentTemplate>

...我确实获取了ContentTitle属性的内容而不是item,因此属性本身是可绑定的。

这是IMovable界面:

public interface IMovable : INotifyPropertyChanged
{
    string ContentTitle { get; }
}

所以我的问题是:ItemTemplate中是否有不同的DataContext(如果是这样,它是什么?)或者是否有其他原因导致ItemTemplate中的绑定无法正常工作?

<击>的更新 我已经创建了一个小例子应用程序,可以清楚地显示问题。如果事情按预期工作,则每个选项卡中的每个Ellipse下面都会有一个文本,而Ellipse的DataContext将不为null。它可以在这里下载:Example App

更新 如果使用自定义类Foo::DependencyObject并将ContentTitle属性设置为DependencyProperty,则它可以正常工作。虽然更改原始类中的属性不起作用。我需要睡在这...... [/ p>

更新 我已经缩小了问题范围,但调查结果与我的预期完全不同。 WpfApplication2表明向ItemsSource添加POCO或从DependedcyObject派生的项目按预期工作。但是,从UserControl派生的项目不会给出预期的结果。如果有人看看你,我将不胜感激。只需运行该应用程序,您就会看到一个Tab标题缺少文本。

4 个答案:

答案 0 :(得分:3)

重写ItemContainerStyle而不是ItemTemplate为我工作:

<TabControl 
    SelectedIndex="{Binding ElementName=this, Path=SelectedIndex}" 
    ItemsSource="{Binding ElementName=this, Path=Items}" 
    TabStripPlacement="Left"  
    Visibility="{Binding ElementName=this, Path=ShowTabs, Converter={StaticResource    _trueToVisibleConverter}}">
    <TabControl.ItemContainerStyle>
        <Style TargetType="{x:Type TabItem}">
            <Setter Property="Header" Value="{Binding Path=Title}" />
        </Style>
    </TabControl.ItemContainerStyle>
    <TabControl.ContentTemplate>
        <DataTemplate>
            <ContentControl Content="{Binding}" />
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

根据以下MSDN帖子,问题是我试图将我绑定到的UIElement添加到可视树中的两个不同位置(内容区域和标题区域)。请参阅帖子以获得更好的解释。

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/0a4622ac-5990-4b6e-bf38-0acb10cd68c7/

答案 1 :(得分:0)

我也需要vm代码以确保,但看起来上下文位于主vm内,而不是表示每个标签项的子vm,内容模板上下文是主vm和项模板上下文tab vm。

答案 2 :(得分:0)

是的,他们是一样的。因此,如果绑定到{Binding}中的ContentTemplate,则会绑定到对象本身。

在您的情况下:ItemTemplate有一个IMovable对象作为数据上下文,实际上ContentTemplate具有相同的数据上下文:IMovable对象。

您可能认为ItemTemplate 选择其他数据上下文。事实并非如此。

答案 3 :(得分:0)

这里的问题是DataTemplate会看到一个继承自Visual的对象。这种类型的对象不需要通过DataTemplate进行任何可视化表示。这篇文章对此进行了讨论。

DataTemplate DataType property doesn't work on types inherited from Control