WPF TabControl 与 DataTemplate 的行为非常奇怪

hpa*_*alu 5 silverlight wpf xaml tabcontrol datatemplate

如果将控件放入 DataTemplate 中,为什么它们的各个状态会复制或反映在 TabControl 中的每个选项卡中?你在一个选项卡中更改它,所有其他选项卡都会反映,这是为什么?!在我看来,TabControl 仅初始化一个模板化的 ContentControl,并且每次单击选项卡都会重新复制其中的整个内容 - 使旧的控件状态保持不变。要明白我的意思,请考虑将其放入您的 XAML-Pad 中:

<TabControl>
  <TabControl.ContentTemplate>
    <DataTemplate>
      <Border>
        <TextBox Text="test"/>
      </Border>
    </DataTemplate>
  </TabControl.ContentTemplate>
  <TabItem Header="Tab1"/>
  <TabItem Header="Tab2"/>
</TabControl>
Run Code Online (Sandbox Code Playgroud)

它将创建一个带有两个模板化选项卡的 TabControl。现在在文本框中输入一些内容并切换到另一个选项卡,输入的文本将保留。现在每个选项卡将具有相同的内容。我没有在 ListBox 或任何其他控件中观察到相同的行为,这使得实际工作非常困难,因为每一点都需要绑定到 ViewModel 才能使其在 TabControl 中可用。当我在 DataTemplate 中使用的扩展器在我的所有选项卡中弹出时,我注意到了这种奇怪的行为,尽管我专门解决了一个问题。作为一种解决方法,我必须将“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 );
    }
}
Run Code Online (Sandbox Code Playgroud)

Aka*_*ava 2

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

TabControl 这样做是为了节省内存,在数据模板的情况下,切换选项卡时控件保持不变,但它的底层绑定数据上下文发生了变化,并且绑定反映了正确的数据。因此,视觉上您感觉选项卡已更改,但实际上只有数据更改,但控件保持不变。这称为 ui 虚拟化。

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