Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.5k views
in Technique[技术] by (71.8m points)

wpf - How can I access a ListBox within a TabControl.ContentTemplate?

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...