带有绑定表项的TabControl的逻辑子控件

本文关键字:控件 TabControl 绑定 | 更新日期: 2023-09-27 18:02:37

我有一个TabControl,它的ItemsSource绑定到ObservableCollection<string>。在本例中,TabControl没有逻辑子节点(LogicalTreeHelper.GetChildren(tabctrl)返回一个空列表)。

如果我手动添加TabItemTabControl.Items集合,TabItem是TabControl的逻辑子。

为什么这些方式的行为不同?在这两种情况下,TabControl不应该有一个逻辑子节点吗?

示例代码:

XAML

<Window x:Class="WpfApplication29.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
  <StackPanel>
    <TabControl Name="tabctrl"/>
    <Button Content="count children" Click="Button_Click_2"/>
  </StackPanel>
</Window>

代码后面

using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace WpfApplication29
{
  public partial class MainWindow : Window
  {
    public ObservableCollection<string> TabItems
    {
      get { return (ObservableCollection<string>)GetValue(TabItemsProperty); }
      set { SetValue(TabItemsProperty, value); }
    }
    public static readonly DependencyProperty TabItemsProperty =
        DependencyProperty.Register("TabItems", typeof(ObservableCollection<string>), typeof(MainWindow), new PropertyMetadata(null));
    public MainWindow()
    {
      InitializeComponent();
      TabItems = new ObservableCollection<string>();
      TabItems.Add("foo");
      //scenario 1 (Visual Children count: 1, logical children count: 0)
      tabctrl.SetBinding(TabControl.ItemsSourceProperty, new Binding("TabItems") { Source = this });
      //scenario 2 (Visual Children count: 1, logical children count: 1)
      //tabctrl.Items.Add(new TabItem() { Header = "bar", Content = "bar" });
    }
    private void Button_Click_2(object sender, RoutedEventArgs e)
    {
      var visualChildrenCount = VisualTreeHelper.GetChildrenCount(tabctrl);
      var logicalChildrenCount = LogicalTreeHelper.GetChildren(tabctrl).Cast<object>().Count();
      MessageBox.Show(string.Format("Visual Children: {0}, Logical Children: {1}", visualChildrenCount, logicalChildrenCount));
    }
  }
}

带有绑定表项的TabControl的逻辑子控件

如果您添加一个控件到您的用户控件,或页面,它被添加到它的LogicalTree。但是,控件模板中的ui元素不是LogicalTree的一部分。

IMHO,当您直接将TabItem添加到TabControl时,您希望直观地出现在LogicalTree中。你已经直接添加到那里了。

但是当item从itemssource生成时,TabItems是由控件的内部逻辑生成的,而不是添加到LogicalTree中。

也许更好的例子是ListBox或DataGrid。假设您将ItemsSource绑定到非常大的集合,并且需要启用虚拟化。然后只在需要时生成项目(ui元素)(它们位于滚动查看器的可见区域)。如果它们位于逻辑树中,则逻辑树将在滚动时发生变化。但是滚动更多的是关于视觉而不是"UI逻辑"。

本文有助于更好地理解逻辑树:http://www.codeproject.com/Articles/21495/Understanding-the-Visual-Tree-and-Logical-Tree-in