VisualTreeHelper.GetChildren не находит дочерних элементов TabItem
У меня есть следующий код C#, чтобы найти детей DepedendencyObject:
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject parent) where T : DependencyObject
{
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
T childType = child as T;
if (childType == null)
{
foreach (var other in FindVisualChildren<T>(child))
yield return other;
}
else
{
yield return (T)child;
}
}
}
Когда я перебираю TabItems в XAML, размещенном внизу, передавая каждый TabItem вышеуказанному методу, прося его найти все Expanders, он ничего не возвращает. Кроме того, я делаю этот запрос в обработчике событий, прикрепленном к событию Loaded каждого элемента вкладки.
<TextBlock Text="Number of Parts" Grid.Column="0"/>
<ComboBox Grid.Column="2"
Margin="0,0,0,2"
/>
</Grid>
</Expander>
<Expander Header="Date/Time Format"
Margin="5,0,5,0"
Padding="3,3,0,0"
IsExpanded="True" >
<Grid Margin="20,4,0,4">
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="Date/Time Format" Grid.Row="0"/>
<ComboBox Name="cmbDateTimeFormats"
Grid.Row="0" Grid.Column="2"/>
</Grid>
</Expander>
</StackPanel>
</DockPanel>
</Border>
</TabItem>
<TabItem Header="Profile">
<Border >
<DockPanel LastChildFill="False">
<StackPanel DockPanel.Dock="Top">
<GroupBox Header="Local"
Margin="5,8" Padding="3,3,0,0"
>
<Grid Margin="20,4,0,4">
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Content="Location..." Grid.Row="0" Name="btnProfLoc" />
<TextBlock Text="{Binding ProfileLocation}" Grid.Row="0" Grid.Column="2"/>
<Button Name="btnSaveProfile" Height="25"
Margin="2,5,0,0" Grid.Row="1"
Padding="2,1" >
<StackPanel Orientation="Horizontal">
<TextBlock Text="Save" Margin="5,0"/>
</StackPanel>
</Button>
<Button Name="btnLoadProfile" Height="25"
Margin="2,5,0,0" Grid.Row="2"
Padding="2,1" >
<StackPanel Orientation="Horizontal">
<TextBlock Text="Load" Margin="5,0"/>
</StackPanel>
</Button>
<Button Name="btnResetProfile" Height="25"
Margin="2,5,0,0" Grid.Row="3"
Padding="2,1" >
<StackPanel Orientation="Horizontal">
<TextBlock Text="Reset" Margin="5,0"/>
</StackPanel>
</Button>
</Grid>
</GroupBox>
</StackPanel>
<StackPanel
DockPanel.Dock="Bottom" Orientation="Horizontal">
</StackPanel>
</DockPanel>
</Border>
</TabItem>
</TabControl>
Есть предположения, что не так с моим подходом? Я не пробовал в этом конкретном пользовательском элементе управления, но этот метод использовался для поиска дочерних элементов данного типа в другом пользовательском элементе управления. Основное отличие состоит в том, что предметы, которые я ищу, являются детьми TabItems.
1 ответ
Элементы управления внутри вкладки не являются потомками элемента TabItem в визуальном дереве. Они дети TabControl.
Вы можете понять, что я имею в виду, если добавите следующий код в свое приложение... и включите кнопку на вкладке с обработчиком щелчков, который сообщает путь к кнопке.
public string Id(object control)
{
if (control is UIElement)
{
string id = ((UIElement)control).GetValue(AutomationProperties.AutomationIdProperty).ToString();
id += "(" + control.GetType().Name + ")";
return id;
}
return "not a ui element";
}
private static T FindParent<T>(DependencyObject child)
where T : DependencyObject
{
if (child == null) return null;
var parent = VisualTreeHelper.GetParent(child);
return parent as T ?? FindParent<T>(parent);
}
public string Path(object control)
{
if ( control == null ) return "";
var path = Id(control);
var parent = FindParent<FrameworkElement>(control as UIElement);
if (parent != null ) path = Path(parent) +"/"+ path;
return path;
}
Для моего приложения я получаю следующее: "MainForm(MainPage)/(Сетка)/(StackPanel)/TabControl(TabControl)/(Сетка) / (Сетка) / (Граница)/(ContentPresenter)/(StackPanel)/ Кнопка (кнопка)"
Обратите внимание на TabControl, но нет TabItem.
Если я подключаюсь к событиям из самого TabItem, я получаю следующий путь: "MainForm(MainPage)/(Grid)/(StackPanel)/TabControl(TabControl)/(Grid)/(Grid)/(TabPanel)/ (TabPanel) / MyTabItem(TabItem)"
Это показывает, что элементы не существуют в TabItem в визуальном дереве, но являются дочерними элементами TabControl. (Который отстой.) Примечание: они виртуализируются и реализуются при смене вкладок.