How to find control from datatemplate of tabitem wpf

淺唱寂寞╮ 提交于 2019-12-11 01:48:47

问题


I have 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>

How I can get listbox programmatically in C# code?

I have tried below code and myContentPresenter.ContentTemplate shows 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);

回答1:


Building on @mm8 approach, the following solution will find the ListBox by name instead of by type:

XAML

<TabControl x:Name="tabControl1" SelectionChanged="tabControl1_SelectionChanged">
    <TabItem  x:Name="tab1" Header="ABC">
        <TabItem.ContentTemplate>
            ...

Code

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:


The ListBox is not a visual child of the TabItem but it is a visual child of the TabControl itself provided that the "ABC" tab is actually selected.

You need to wait for it to get added to the visual tree before you can access it though. This should work:

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());
        }));
    }
}

Only the elements of the currently visible TabItem are added to the visual tree. When you switch tabs, the invisible elements are removed.




回答3:


You can use the following function to get the Visual Child of a WPF control:

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

Usage:

ListBox lb = MainWindow.FindVisualChild<ListBox>(tabControl);


来源:https://stackoverflow.com/questions/44492970/how-to-find-control-from-datatemplate-of-tabitem-wpf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!