Cant get a control from a TabControl DataTemplate

2019-02-23 01:21发布

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 :)

1条回答
成全新的幸福
2楼-- · 2019-02-23 01:43

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);
    }));
查看更多
登录 后发表回答