In my code behind I set the MessageBoxTabControl.ItemsSource to an Observable Collection.
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.
Should be this:
TabItem relevantTabItem = howeverYouGetThisThing();
var grid = System.Windows.Media.VisualTreeHelper.GetChild(relevantTabItem, 0);
var listBox = (ListBox) System.Windows.Media.VisualTreeHelper.GetChild(grid, 0);