Не могу получить элемент управления из шаблона данных TabControl - PullRequest
5 голосов
/ 04 июня 2011

Я гуглял это последние 2 дня и не могу никуда добраться, я просто не могу ничего сделать с любым элементом управления в таблице данных tabcontrol.

Во-первых, код:

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>

Вкратце эта строка:

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

выдает ошибку «System.InvalidOperationException» Эта операция действительна только для элементов, к которым применен этот шаблон.

эта конкретная идея, которую я получил от здесь

У меня естьнашел множество других способов сделать это, но я, кажется, никуда не денусь :( надеюсь, кто-то может указать мне правильное направление:)

1 Ответ

9 голосов
/ 04 июня 2011

Похоже, проблема в том, как TabControl создается во время выполнения. Похоже, что в первый раз, когда вызывается событие SelectionChanged, ContentTemplate не совсем готов для доступа. Если вы снова запустите свой код и пропустите первый доступ к ContentTemplate, вы увидите, что в последующих событиях вы можете получить доступ к этому свойству без исключения.

Часто эти типы ошибок можно преодолеть, вызвав Dispatcher.BeginInvoke, в этом случае он позволяет среде выполнения завершить инициализацию элемента управления вкладкой перед выполнением вашего кода.

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);
    }));
...