Close button on TabControl/TabItem

6 posts, 0 answers
  1. Alessandro
    Alessandro avatar
    31 posts
    Member since:
    Oct 2010

    Posted 17 Feb 2011 Link to this post

    Hi,
     I am modifying the example shown here: http://www.telerik.com/community/forums/silverlight/tabcontrol/how-to-close-the-tab.aspx to accomplish having a close button on my Tab Header control. Basically I don't want to bind my RadTabControl to a list, but rather to create the RadTabItems programatically. The reason is because the content for each TabItem may differ substantially (we are dynamically generating that content).  However, I would sill like to bind the the TabItem to a class.  My HeaderTemplate is defined as:

    <Style TargetType="my:RadTabItem">
        <!--Set a template for the header:-->
        <Setter Property="HeaderTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <ContentControl Content="{Binding Id}" />
                        <Button Grid.Column="1" Margin="3 0 0 0" Content="x" Width="12"
                                Height="12" HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                telerikrouted:EventHelper.EnableRoutedClick="True" />
                    </Grid>
                </DataTemplate>
            </Setter.Value>
        </Setter>

    This is what the logic looks like where I create my TabItems. I've cleaned it up to make it easier to see:
    var newTab = new RadTabItem();
    newTab.DataContext = MyObject; // This object has an Id property
     
    ViewItem viewItem = new ViewItem()
    newTab.Content = viewItem;
     
    MyTabControl.Items.Add(newTab);

    Probably is that the ID is not displayed properly in the Tab Header. After some testing I tried binding the TabControl to a list of MyObject instance and that seemed to make the header display correctly. But I really can't do that. Any ideas?

    Maybe there is a way to do this without binding the TabItem at all?

     -- xavier


  2. Alessandro
    Alessandro avatar
    31 posts
    Member since:
    Oct 2010

    Posted 18 Feb 2011 Link to this post

    Ok, so figured out how to add the button to the RadTabItem head using a DataTemplate. I also can do this where I am creating the RadTabItem's programatically. My code looks something like this:

    var newTab = new RadTabItem();
    newTab.DataContext = MyObject;
    newTab.Header = trackedEntity.ToShortString();
    newTab.HeaderTemplate = Application.Current.Resources["RadTabHeaderTemplate"] as DataTemplate;
     
     // Add the Content to this tab
    ViewItem viewItem = new ViewItem()
    newTab.Content = viewItem;
      
    // Add the Tab to the RadTabControl
    MyTabControl.Items.Add(newTab);

    The RadTabHeaderTemplate is defined as:

    <DataTemplate x:Key="RadTabHeaderTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="50" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <ContentControl Grid.Column="0" Content="{Binding Path=Id}" />
                <Image Grid.Column="1" Source="/COBRA5;component/Media/Buttons/SearchIcon.png" Width="25" />
                <Button Grid.Column="2" Margin="3 0 0 0" Content="x" Width="12"
                      Height="12" HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                        telerikrouted:EventHelper.EnableRoutedClick="True" />
            </Grid>
        </DataTemplate>

    here are the problems I am Having.

    1. I want to bind the controls in the DataTemplate to properties of the MyObject class. Specifically, MyObject.Id and MyObject.ImageSource. I can't seem to get this binding to work.

    2. In the OnClick event of the button, How do I get access to the DataContext of the RadTabItem.  This is what I currently have, what do I need to add to access the MyObject Datacontext from the line above:

    newTab.DataContext = MyObject;

    here is what I have now:

    public void OnCloseClicked(object sender, RoutedEventArgs e)
    {
        var radEventArgs = e as RadRoutedEventArgs;
        var button = radEventArgs.Source as Button;
        // ???? What code to I need to get to the RadTabItem.DataContext from here?????
     
    }

    Finally, for the RadTabControl, I use DropDownDisplayMode="Visible". However, this shows everything in the RadTabHeaderTemplate (button, image and text) in the dropdown. Can I create a separate template to display only the text in the dropdown?

    Thanks for any help you can offer here.

  3. DevCraft banner
  4. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 18 Feb 2011 Link to this post

    Hello Xavier,

    I prepared a sample for you that shows the proffered approach in this situation. Basically, it uses TabIteViewModel and the TabControl is bound to an ObservableCollection of ViewModels.
    Do not hesitate to ask if you need more info on this.

    Regards,
    Petar Mladenov
    the Telerik team
  5. Alessandro
    Alessandro avatar
    31 posts
    Member since:
    Oct 2010

    Posted 18 Feb 2011 Link to this post

    Peter,
      First, thank you for your response. I was hoping that I was clear on one particular point and that is that we cannot bind the TabControl to a viewmodel for various reasons. Therefore, we would need to be able to bind the TabItem itself to the view model as such:

    var newTab = new RadTabItem();
    newTab.DataContext = MyViewModel;

    At that point, it should not matter that the TabControl itself is not bound to a list. Is this not possible with the TabControl?  If it is possible, then I would l need to have the other questions answered:

    1.How do I bind the controls defined in the DataTemplate to properties of the MyViewModel class?
    2. How do I access the ViewModel in the OnClick event of the button on the head and then how can I tell the TabControl to remove the specified tab since it is not bound to a list?

    Please let me know if this is impossible.  Thanks Peter!

     -- xavier
  6. Alessandro
    Alessandro avatar
    31 posts
    Member since:
    Oct 2010

    Posted 18 Feb 2011 Link to this post

    Peter,
      I believe I have figured it out. Basically, it requires the following code:

    var newTab = new RadTabItem();
    newTab.DataContext = MyViewModel;
    newTab.Header = MyViewModel;   //

    Apparently, the Header is not linked to it's parent's Datacontext.  This is a good find.
  7. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 21 Feb 2011 Link to this post

    Hello Xavier,

    This is expected behavior of the RadTabItem. When you create the TabItems programatically, the usual approach requieres setting Header and Content. The DataContext actually is needless in your last code if you set the both Content and the Header like so:
    private void Button_Click(object sender, RoutedEventArgs e)
           {               
               TabItemHeader viewModel= new TabItemHeader()
               {
                   ID = DateTime.Now.ToString(),
                   ImgSource = new BitmapImage(new Uri("Image/OK.png", UriKind.RelativeOrAbsolute)),
                     
               };
               TabItemContent content = new TabItemContent()
               {
                   Content = new Rectangle() { Width = 100, Height = 100, Fill = new SolidColorBrush() { Color = Colors.Cyan } }
               };
               var newTab = new RadTabItem();
               newTab.Header  = viewModel;
               newTab.Content = content;
               newTab.Style = this.LayoutRoot.Resources["tabHeaderStyle"] as Style;
               this.tabControl.Items.Add(newTab);
           }
    <Grid.Resources>
                <Style x:Key="tabHeaderStyle" TargetType="telerik:RadTabItem">
                    <Setter Property="HeaderTemplate">
                        <Setter.Value>
                            <DataTemplate >
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*" />
                                        <ColumnDefinition Width="50" />
                                        <ColumnDefinition Width="Auto" />
                                    </Grid.ColumnDefinitions>
                                    <ContentControl Grid.Column="0" Content="{Binding ID}" />
                                    <Image Grid.Column="1" Source="{Binding ImgSource}" Width="20" Height="20" />
                                    <Button Grid.Column="2" 
                                            Width="20"
                                            Height="20"
                                            HorizontalAlignment="Center"
                                            VerticalAlignment="Center"
                                            Content="x" />
                                </Grid>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate >
                                <Grid>
                                    <ContentControl Content="{Binding Content}" />
                                </Grid>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Grid.Resources>
      
            <StackPanel Orientation="Vertical">
                <telerik:RadTabControl x:Name="tabControl" />
                <Button Click="Button_Click" Content="AddTabItem" />
            </StackPanel>
    Feel free to ask if you need more info.

    Kind regards,
    Petar Mladenov
    the Telerik team
Back to Top
DevCraft banner