带有DataTemplate的WPF TabControl表现得很奇怪

时间:2011-10-09 11:22:18

标签: wpf silverlight xaml datatemplate tabcontrol

如果您将控件放在DataTemplate中,为什么它们的各个状态会复制或反映在TabControl的每个Tab中?你在一个标签中更改它,所有其他标签都反映出来,为什么会这样?!在我看来,TabControl只初始化一个模板化的ContentControl,每次点击Tab都会重新复制整个内容 - 让旧的控制状态保持不变。看看我的意思是考虑把它放在你的XAML-Pad中:

<TabControl>
  <TabControl.ContentTemplate>
    <DataTemplate>
      <Border>
        <TextBox Text="test"/>
      </Border>
    </DataTemplate>
  </TabControl.ContentTemplate>
  <TabItem Header="Tab1"/>
  <TabItem Header="Tab2"/>
</TabControl>

它将创建一个带有两个模板化选项卡的TabControl。现在在TextBox中输入一些内容并切换到另一个Tab,输入的文本将继续。每个标签现在都有相同的内容。我没有在ListBox或任何其他控件中观察到相同的行为,它使得实际工作非常困难,因为每一点都需要绑定到ViewModel以使其在TabControl中可用。当我在DataTemplate中使用的Expanders在我的所有选项卡中弹出时,我注意到这种奇怪的行为,尽管我专门解决了一个问题。作为一种解决方法,我必须将“IsExpanded”绑定到ViewModel中的属性,但它真的很糟糕。

任何人都知道这里发生了什么?


<TabControl x:Name="MainTab" SelectedIndex="0"/>
...
Collection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Collection_CollectionChanged);
...
void Collection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        TabItem MyNewItem = new TabItem();
        ContentPresenter MyContentPresenter = new ContentPresenter();
        MyContentPresenter.ContentTemplate = (DataTemplate)this.FindResource("MyTemplate");
        MyContentPresenter.Content = e.NewItems[0];
        MyNewItem.Content = MyContentPresenter;                
        MainTab.Items.Add(MyNewItem );
    }
}

2 个答案:

答案 0 :(得分:3)

行为是完美的,有办法解决这个问题。必须仅在绑定时使用DataTemplate。将可枚举项目源分配给选项卡控件时,您的数据模板应该包含一个或两个方式的绑定。如果是文本框,则应该是双向绑定。

TabControl执行此操作以节省内存,在数据模板的情况下,切换选项卡时控件保持不变,但是底层绑定的datacontext是什么更改,绑定反映正确的数据。因此,您可以在视觉上看到标签已更改,但实际上只有数据更改,但控制保持不变。这称为ui虚拟化。

在您的情况下,除非将某些内容绑定到项目源,否则不应使用数据模板。否则,您必须使用项目容器样式。

答案 1 :(得分:2)

WPF中的TabControls有点令人讨厌。例如,当您切换选项卡时,它会破坏第一个选项卡上的所有内容,并加载第二个选项卡的控件。唯一没有被破坏/重新创建的是所有选项卡上存在的控件,例如在TabItem的模板中创建的TextBox。

因此你的TextBox在其他标签上被重复使用,并且由于TextBox.Text没有绑定任何东西,所以在切换标签时它保持不变。

要更改此行为,请将TextBox.Text值绑定到某个值,或者使用它自己的TextBox版本创建每个TabItem。

<TabControl>
    <TabItem Header="Tab1">
        <local:TabControlContent />
    </TabItem>
    <TabItem Header="Tab2">
        <local:TabControlContent />
    </TabItem>
</TabControl>