首页 文章

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

提问于
浏览
3

如果您将控件放在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 回答

  • 2

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

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

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

  • 3

    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>
    

相关问题