Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cant get a control from a TabControl DataTemplate

I've been googling this for the last 2 days and cant get anywhere, I just cant do anything to any control in a datatemplate of a tabcontrol.

First off, the code:

private void Window_Loaded(object sender, RoutedEventArgs e) {
    tabControl1.ItemsSource = new string[] { "TabA", "TabB", "TabC" };
}

private void tabControl1_SelectionChanged(object sender, SelectionChangedEventArgs e) {
    ContentPresenter cp = tabControl1.Template.FindName("PART_SelectedContentHost", tabControl1) as ContentPresenter;

    DataTemplate dt = tabControl1.ContentTemplate;
    Grid g = tabControl1.ContentTemplate.FindName("myGrid", cp) as Grid;
    g.Background = new SolidColorBrush(Colors.Red);
}

xaml

<Window x:Class="tabTest.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" Loaded="Window_Loaded">
<Grid>
    <TabControl IsSynchronizedWithCurrentItem="True" Height="140" Name="tabControl1" Width="230" SelectionChanged="tabControl1_SelectionChanged">
        <TabControl.ContentTemplate>
            <DataTemplate>
                <Grid x:Name="myGrid">                        
                </Grid>
            </DataTemplate>    
        </TabControl.ContentTemplate>            
    </TabControl>
</Grid>

In short this line:

Grid g = tabControl1.ContentTemplate.FindName("myGrid", cp) as Grid;

throws an error "System.InvalidOperationException" This operation is valid only on elements that have this template applied.

this particular idea i got from here

I've found loads of other ways of doing this but I cant seem to get anywhere :( hope someone can point me in the right direction :)

like image 511
Julian Avatar asked Jun 03 '11 20:06

Julian


People also ask

How to access datatemplate controls in code behind?

We can not access DataTemplate controls in code behind. So for this you have to use ICommand interface inside your ViewModel. So it is clear that you should be use MVVM pattern. And important is that use of Command property is not a complex task. Can you please refer this links.

What happens if there is no key in a datatemplate?

If it finds a DataTemplate that has a matching DataType but no key, it will use it to render the view model. If it doesn't find one, it'll default to rendering the ToString value of the object.

Why does WPF use tostring instead of datatemplate?

Since you're not being specific, WPF is attempting to walk up your logical tree to find an appropriate DataTemplate. When it finds it, it uses it to render the view model. Where it doesn't find it, it calls ToString and renders that.

Why does WPF use the same datatemplate for multiple view models?

Therefore, WPF searches for an appropriate DataTemplate for both. Since both contain an instance of your view model (that's their DataContext) then the same DataTemplate will be used to render tab headers and their contents. NOTE: you didn't explicitly state that this is what's happening in your question.


1 Answers

Looks like it's issue with the way the TabControl is being instantiated by the run time. It appears that the first time the SelectionChanged event is being raised the ContentTemplate is not quite ready to be accessed. If you run your code again and skip over the first access of ContentTemplate you'll see that in subsequent events you can access this property without the exception being thrown.

Often these types of errors can be overcome by calling Dispatcher.BeginInvoke, in this case it allows the run time to finish initializing the tab control before executing your code.

Dispatcher.BeginInvoke(new Action(() =>
    {
        ContentPresenter cp = tabControl1.Template.FindName("PART_SelectedContentHost", tabControl1) as ContentPresenter;
        Grid g = tabControl1.ContentTemplate.FindName("myGrid", cp) as Grid;
        g.Background = new SolidColorBrush(Colors.Red);
    }));
like image 107
Ian Oakes Avatar answered Oct 05 '22 08:10

Ian Oakes