This is a migrated thread and some comments may be shown as answers.

How to find control in ContentTemplate

4 Answers 754 Views
TabControl
This is a migrated thread and some comments may be shown as answers.
A
Top achievements
Rank 1
A asked on 06 Mar 2014, 07:58 AM
I have RadTabControl with RadGridView in the ContentTemplate. I need bind this RadGridView as a command parameter to the button, that is outside the RadTabControl. Is there a way to do that? Looks like such feature is missing in your controls

4 Answers, 1 is accepted

Sort by
0
Martin Ivanov
Telerik team
answered on 10 Mar 2014, 04:54 PM
Hi,

When you define a visual element within a DataTemplate, this element is generated and loaded when the DataTemplate gets applied. Additionally as the element is not directly part of the visual tree (as it gets applied as part of a DataTemplate), it is not a straight-forward task to access it. Basically what you can do is implement a code-behind logic that traverses the visual tree to find the RadGridView after the ContentTemplate in which it is defined is applied. 

For that purpose you first need to consider the fact that RadTabControl loads the Content of its tabs on demand. This means that if the first item is selected its Content will be loaded. Then when you select another item the Content of the first one will be removed from the visual tree and the Content of the currently selected item will be generated. 

This is why in order to get the RadGridView you can either:
  • handle the RadGridView Loaded event. If you define a GridView in every tab then this would mean that the Loaded event will be invoked when the tab selection changes (when a new RadGridView instance is created). Then you can set the sender as a CommandParameter of a Button. You can see this implementation in the attached project. Also here is an example in code:
private void gridView_Loaded(object sender, RoutedEventArgs e)
{
    var gridView = sender as RadGridView;
    if (VisualTreeHelper.GetParent(gridView) != null)
    {
        this.btn.CommandParameter = gridView;
    }
}

<Window.Resources>
    <sys:String x:Key="charCollection">abcdef</sys:String>
     
    <DataTemplate x:Key="tabControlContentTemplate">
        <telerik:RadGridView x:Name="gridView" ItemsSource="{StaticResource charCollection}" Loaded="gridView_Loaded" />
    </DataTemplate>
</Window.Resources>
 
<Grid>
    <telerik:RadTabControl  Name="tabControl"
  ContentTemplate="{StaticResource tabControlContentTemplate}"
  ItemsSource="{StaticResource charCollection}" />
    <Button Name="btn"
            Content="Execute Command"
            Loaded="Button_Loaded"
            VerticalAlignment="Bottom" />
</Grid>
  • handle the RadTabControl SelectionChanged event to get the RadGridView with the ChildrenOfType<T>() method:
var gridViews = this.tabControl.ChildrenOfType<RadGridView>();

Both options traverse the visual tree which sometimes can be a heavy task. This is why if you can share more information about your requirements and why you need to pass the RadGridView as a CommandParameter we might be able to suggest a different approach.

For instance, if you need to use a GridViewCommand, you can place the Button on a RadToolBar. The ToolBar is a focus scope and therefore it doesn't steal the focus away from the other elements on the screen. This allows its buttons to detect other focused elements and use them as targets of their commands.
<Window.Resources>
    <DataTemplate x:Key="tabControlContentTemplate">
        <telerik:RadGridView x:Name="gridView" ItemsSource="{Binding Products}"/>
    </DataTemplate>
    <DataTemplate x:Key="HeaderTemplate">
        <TextBlock Text="{Binding Header}"/>
    </DataTemplate>
</Window.Resources>
 
    ............................
 
<telerik:RadToolBar VerticalAlignment="Top">
    <Button 
        Content="Delete" Command="telerik:RadGridViewCommands.Delete"/>
</telerik:RadToolBar>
<telerik:RadTabControl IsContentPreserved="True" Name="tabControl" Grid.Row="1"
                       ContentTemplate="{StaticResource tabControlContentTemplate}"
                       ItemsSource="{Binding Items}" ItemTemplate="{StaticResource HeaderTemplate}"
                       SelectionChanged="tabControl_SelectionChanged" Loaded="tabControl_Loaded"/>

Regards,
Martin
Telerik
 

DevCraft Q1'14 is here! Watch the online conference to see how this release solves your top-5 .NET challenges. Watch on demand now.

 
0
Petr
Top achievements
Rank 1
answered on 22 May 2014, 03:23 PM
Hello, I have SalusRadTabConrol inherited from RadTabControl. Used like this with defined ContentTemplate.

<controls:SalusRadTabControl BorderThickness="0" Grid.Column="0" HeaderBackground="{StaticResource VitalSignsMainColor}" Foreground="White"
                                         ItemsSource="{Binding MeasurementCategories}"
                                         SelectedItem="{Binding SelectedMeasurementCategory, Mode=TwoWay}"
                                         IsSynchronizedWithCurrentItem="True">                
 
                <telerik:RadTabControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Path=Name, Converter={StaticResource TextToUpperCaseConverter}}" />
                    </DataTemplate>
                </telerik:RadTabControl.ItemTemplate>
 
                <telerik:RadTabControl.ContentTemplate>
                    <DataTemplate>
                        <Grid Background="Transparent" Margin="10" x:Name="contentGrid">
                            <views:ContentView/>
                        </Grid>
                    </DataTemplate>
                </telerik:RadTabControl.ContentTemplate>
 
            </controls:SalusRadTabControl>

Content view (used in content template) contains as one of his child element RadGridView.

But when try to find RadGridView by ChildrenOfType method in OnSelectionChanged event callback on SalusRadTabControl, desired element is not found.

protected override void OnSelectionChanged(SelectionChangedEventArgs e)
 {
            base.OnSelectionChanged(e);
 
            var grid = this.FindChildByType<RadGridView>();
 }


Could you please give me advice where is problem? Thanks
0
Martin Ivanov
Telerik team
answered on 27 May 2014, 06:49 AM
Hi Petr,

Note that the content of the tab control may be loaded after the selection is executed. This is why in your case the FindChildByType<T> method cannot find the GridView. In order to get it you can set your code in Dispatcher. This will ensure that the content of the selected item is loaded before the execution of the search code.
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
    base.OnSelectionChanged(e);
 
    Dispatcher.BeginInvoke(new Action(() => {
        var grid = this.FindChildByType<RadGridView>();
    }));
     
}

Regards,
Martin
Telerik
 
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
 
0
skrec
Top achievements
Rank 1
answered on 31 Jul 2014, 01:53 PM
Late but ... thanks a lot for answer. Petr
Tags
TabControl
Asked by
A
Top achievements
Rank 1
Answers by
Martin Ivanov
Telerik team
Petr
Top achievements
Rank 1
skrec
Top achievements
Rank 1
Share this question
or