Welcome to 16892 Developer Community-Open, Learning,Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

In my code behind I set the MessageBoxTabControl.ItemsSource to an Observable Collection.

<TabControl x:Name="MessageBoxTabControl">
    <TabControl.ContentTemplate>
        <DataTemplate>
            <ListBox x:Name="MessageListBox" />
                <!-- ^ I want a reference to this control -->
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

Assuming I have the relevant tabcontrol and tabitem, how can I get a reference to my ListBox?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
2.3k views
Welcome To Ask or Share your Answers For Others

1 Answer

Have you thought about doing whatever you want to do some other way? Normally, when you have a DataTemplate, any properties you could want to set on the controls inside that template should either be static (so why access them) or depend upon the data supplied, which then should be implemented by a DataBinding.

You can use the following code to get the ListBox. I still feel it would be better to rethink your structure instead of using this code.

Xaml:

<Window x:Class="WpfApplication1.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">

    <TabControl x:Name="MessageBoxTabControl">
        <TabControl.ContentTemplate>
            <DataTemplate >
                <ListBox x:Name="MessageListBox" >
                    <ListBoxItem Content="ListBoxItem 1" /> <!-- just for illustration -->
                </ListBox>
            </DataTemplate>
        </TabControl.ContentTemplate>
        <TabItem Header="Tab 1" />
        <TabItem Header="Tab 2" />
    </TabControl>
</Window>

Code behind:

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    ListBox lbx = FindVisualChildByName<ListBox>(this.MessageBoxTabControl, "MessageListBox");
    if (lbx != null)
    {
        // ... what exactly did you want to do ;)?
    }
}

private T FindVisualChildByName<T>(DependencyObject parent, string name) where T : FrameworkElement
{
    T child = default(T);
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
    {
        var ch = VisualTreeHelper.GetChild(parent, i);
        child = ch as T;
        if (child != null && child.Name == name)
            break;
        else
            child = FindVisualChildByName<T>(ch, name);

        if (child != null) break;
    }
    return child;
}

There is also a second, similar way, that actually uses the template, but still depends on the visual tree to get to the ContentPresenter (FindVisualChild implementation analogous to above):

ContentPresenter cp = FindVisualChild<ContentPresenter>(this.MessageBoxTabControl);
ListBox lbx = cp.ContentTemplate.FindName("MessageListBox", cp) as ListBox;

Note that because of this dependency on the visual tree, you will always only find the ListBox of the selected tab with this method.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to 16892 Developer Community-Open, Learning and Share

548k questions

547k answers

4 comments

56.5k users

...