如何从tabitem wpf的数据模板中找到控件
How to find control from datatemplate of tabitem wpf
我有 TabControl:
<TabControl Name="tabControl"
VerticalAlignment="Top"
HorizontalAlignment="Stretch">
<TabControl.Items>
<TabItem x:Name="tab1" Header="ABC">
<TabItem.ContentTemplate>
<DataTemplate>
<ScrollViewer Name="ScrollViewer">
<StackPanel Orientation="Vertical">
<TextBox Name="txt1" HorizontalAlignment="Center" Margin="0,26,0,0" />
<ListBox Name="listBox" DataContext="{Binding Items, Mode=TwoWay}" />
</StackPanel>
</ScrollViewer>
</DataTemplate>
</TabItem.ContentTemplate>
</TabItem>
</TabControl.Items>
</TabControl>
如何在 C# 代码中以编程方式获取列表框?
我试过下面的代码,myContentPresenter.ContentTemplate
显示为空。
TabItem myListBoxItem = (TabItem)(tabControl.ItemContainerGenerator.ContainerFromItem(tabControl.SelectedItem));
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
ListBox listBox = (ListBox)myDataTemplate.FindName("listBox", myContentPresenter);
您可以使用以下函数获取 WPF 控件的 Visual Child:
private static T FindVisualChild<T>(DependencyObject parent) where T : DependencyObject
{
for (int childCount = 0; childCount < VisualTreeHelper.GetChildrenCount(parent); childCount ++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, childCount);
if (child != null && child is T)
return (T)child;
else
{
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
用法:
ListBox lb = MainWindow.FindVisualChild<ListBox>(tabControl);
ListBox
不是 TabItem
的可视子项,但它是 TabControl
本身的可视子项,前提是实际选择了 "ABC" 选项卡。
您需要等待它添加到可视化树中才能访问它。这应该有效:
private void tabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (tabControl.SelectedItem == tab1)
{
tabControl.Dispatcher.BeginInvoke(new Action(() =>
{
ListBox lb = FindVisualChild<ListBox>(tabControl);
MessageBox.Show(lb.Items.Count.ToString());
}));
}
}
只有当前可见的 TabItem
的元素被添加到可视化树中。当您切换选项卡时,不可见的元素将被删除。
基于@mm8 方法,以下解决方案将按名称而不是按类型查找 ListBox
:
XAML
<TabControl x:Name="tabControl1" SelectionChanged="tabControl1_SelectionChanged">
<TabItem x:Name="tab1" Header="ABC">
<TabItem.ContentTemplate>
...
代码
private void tabControl1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Dispatcher.BeginInvoke(new Action(() => TabItem_UpdateHandler()));
}
void TabItem_UpdateHandler()
{
ContentPresenter myContentPresenter = tabControl1.Template.FindName("PART_SelectedContentHost", tabControl1) as ContentPresenter;
if (myContentPresenter.ContentTemplate == tab1.ContentTemplate)
{
myContentPresenter.ApplyTemplate();
var lb1 = myContentPresenter.ContentTemplate.FindName("listBox", myContentPresenter) as ListBox;
}
}
我有 TabControl:
<TabControl Name="tabControl"
VerticalAlignment="Top"
HorizontalAlignment="Stretch">
<TabControl.Items>
<TabItem x:Name="tab1" Header="ABC">
<TabItem.ContentTemplate>
<DataTemplate>
<ScrollViewer Name="ScrollViewer">
<StackPanel Orientation="Vertical">
<TextBox Name="txt1" HorizontalAlignment="Center" Margin="0,26,0,0" />
<ListBox Name="listBox" DataContext="{Binding Items, Mode=TwoWay}" />
</StackPanel>
</ScrollViewer>
</DataTemplate>
</TabItem.ContentTemplate>
</TabItem>
</TabControl.Items>
</TabControl>
如何在 C# 代码中以编程方式获取列表框?
我试过下面的代码,myContentPresenter.ContentTemplate
显示为空。
TabItem myListBoxItem = (TabItem)(tabControl.ItemContainerGenerator.ContainerFromItem(tabControl.SelectedItem));
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
ListBox listBox = (ListBox)myDataTemplate.FindName("listBox", myContentPresenter);
您可以使用以下函数获取 WPF 控件的 Visual Child:
private static T FindVisualChild<T>(DependencyObject parent) where T : DependencyObject
{
for (int childCount = 0; childCount < VisualTreeHelper.GetChildrenCount(parent); childCount ++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, childCount);
if (child != null && child is T)
return (T)child;
else
{
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
用法:
ListBox lb = MainWindow.FindVisualChild<ListBox>(tabControl);
ListBox
不是 TabItem
的可视子项,但它是 TabControl
本身的可视子项,前提是实际选择了 "ABC" 选项卡。
您需要等待它添加到可视化树中才能访问它。这应该有效:
private void tabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (tabControl.SelectedItem == tab1)
{
tabControl.Dispatcher.BeginInvoke(new Action(() =>
{
ListBox lb = FindVisualChild<ListBox>(tabControl);
MessageBox.Show(lb.Items.Count.ToString());
}));
}
}
只有当前可见的 TabItem
的元素被添加到可视化树中。当您切换选项卡时,不可见的元素将被删除。
基于@mm8 方法,以下解决方案将按名称而不是按类型查找 ListBox
:
XAML
<TabControl x:Name="tabControl1" SelectionChanged="tabControl1_SelectionChanged">
<TabItem x:Name="tab1" Header="ABC">
<TabItem.ContentTemplate>
...
代码
private void tabControl1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Dispatcher.BeginInvoke(new Action(() => TabItem_UpdateHandler()));
}
void TabItem_UpdateHandler()
{
ContentPresenter myContentPresenter = tabControl1.Template.FindName("PART_SelectedContentHost", tabControl1) as ContentPresenter;
if (myContentPresenter.ContentTemplate == tab1.ContentTemplate)
{
myContentPresenter.ApplyTemplate();
var lb1 = myContentPresenter.ContentTemplate.FindName("listBox", myContentPresenter) as ListBox;
}
}