如何从tabitem wpf的datatemplate中找到控件

时间:2017-06-12 06:48:16

标签: c# wpf xaml tabcontrol

我有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显示为null。

TabItem myListBoxItem = (TabItem)(tabControl.ItemContainerGenerator.ContainerFromItem(tabControl.SelectedItem));
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
ListBox listBox = (ListBox)myDataTemplate.FindName("listBox", myContentPresenter);

3 个答案:

答案 0 :(得分:3)

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的元素才会添加到可视树中。切换标签时,会删除不可见的元素。

答案 1 :(得分:3)

在@ 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;
    }
}

答案 2 :(得分:1)

您可以使用以下函数获取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);