Close Button on TabControl... again!

6 posts, 0 answers
  1. figueiredorj
    figueiredorj avatar
    68 posts
    Member since:
    Mar 2011

    Posted 11 Aug 2011 Link to this post

    Hi.

    I am trying to use TabControl to display many userControls.
    However I am struggling to achieve how to add the infamous close button.

    Being me a novice with silverlight there is many things that I still can't do, so I am asking for your help.

    <UserControl x:Class="DoisSoft.TTrack.TabsControl.TabsControlView"
                 xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" mc:Ignorable="d"    >
        <UserControl.Resources>
            <Style x:Key="CloseButton" TargetType="Button">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid Background="Transparent" Width="14" Height="14">
                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="CommonStates">
                                        <VisualState x:Name="Normal" />
                                        <VisualState x:Name="MouseOver">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames
                                                        Storyboard.TargetProperty="(UIElement.Visibility)"
                                                        Storyboard.TargetName="FocusEllipse">
                                                    <DiscreteObjectKeyFrame KeyTime="0">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <Visibility>Visible</Visibility>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                                <ColorAnimation Duration="0" To="#FFDC3030"
                                                        Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
                                                        Storyboard.TargetName="FocusEllipse" />
                                                <ColorAnimation Duration="0" To="White"
                                                        Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)"
                                                        Storyboard.TargetName="path" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Pressed">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames
                                                        Storyboard.TargetProperty="(UIElement.Visibility)"
                                                        Storyboard.TargetName="FocusEllipse">
                                                    <DiscreteObjectKeyFrame KeyTime="0">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <Visibility>Visible</Visibility>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                                <ColorAnimation Duration="0" To="Black"
                                                        Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
                                                        Storyboard.TargetName="FocusEllipse" />
                                                <ColorAnimation Duration="0" To="White"
                                                        Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)"
                                                        Storyboard.TargetName="path" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Disabled" />
                                    </VisualStateGroup>
                                    <VisualStateGroup x:Name="FocusStates">
                                        <VisualState x:Name="Focused" />
                                        <VisualState x:Name="Unfocused" />
                                    </VisualStateGroup>
                                </VisualStateManager.VisualStateGroups>
                                <Ellipse x:Name="FocusEllipse" Fill="#FFF13535" Visibility="Collapsed" />
                                <Path x:Name="path" Data="{TemplateBinding Content}" Stroke="#FF898888"
                                        HorizontalAlignment="Center" VerticalAlignment="Center"
                                        StrokeThickness="1" />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
     
            <telerik:ContainerBindingCollection x:Key="ContainerBindings">
                <telerik:ContainerBinding PropertyName="IsSelected" Binding="{Binding IsSelected, Mode=TwoWay}" />
                <telerik:ContainerBinding PropertyName="DataContent" Binding="{Binding DataContent, Mode=TwoWay}" />
            </telerik:ContainerBindingCollection>
            <DataTemplate x:Key="TabItemTemplate" telerik:ContainerBinding.ContainerBindings="{StaticResource ContainerBindings}">
                <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
                    <TextBlock Text="{Binding Header}" />
                    <Button Command="{Binding RemoveItemCommand}" Style="{StaticResource CloseButton}"  Margin="10,0,0,0" Content="M0,0 L6,6 M6, 0 L0,6"
                            ToolTipService.ToolTip="Remove item" />
     
                </StackPanel>
            </DataTemplate>
            <DataTemplate x:Key="ContentTemplate">
                 
                <Grid Background="White" Opacity=".8"/>
            </DataTemplate>
        </UserControl.Resources>
     
     
     
        <Grid x:Name="LayoutRoot" Background="transparent">
            <telerik:RadTabControl x:Name="tabControl" AllowDragReorder="True" IsContentPreserved="True" ItemsSource="{Binding Tabs}">
                 
                </telerik:RadTabControl>
        </Grid>
    </UserControl>

    This is my view on control. I had it working if it were binding to a actual ViewModel, but I am adding programatically my tabItem:
    newTab = new RadTabItem()
                      {
                          Header = menu.Designation,
                          Content = new WOF0100View(_eventAggregator, _fleetService),
                          Tag = menu.Code,
                          IsSelected = true
                      };

    How can I change xaml in order to accept a close button and set my content as user control?
    Thanks in advance

    Ps.
    Telerik could think on having a property on radtabcontrol so if it were enabled it would display close button and his feature as default.
  2. Lilia
    Lilia avatar
    32 posts
    Member since:
    Mar 2011

    Posted 11 Aug 2011 Link to this post

    Have you seen the Telerik online help for adding a close button? It worked like a charm for me.
  3. DevCraft banner
  4. figueiredorj
    figueiredorj avatar
    68 posts
    Member since:
    Mar 2011

    Posted 11 Aug 2011 Link to this post

    Hi Lilia!

    Thanks for trying aid me but that solution didn't helped me...
    This because I want to render UserControl on tab context.. and having content as UserControl doesn't render it.. until now achieved it with default RadTabMap although haven't  a solution for closing it.

    Any more ideas Lilia? (or someone else)

    Edit: I have tried to go on Blend to see if I could do something more... "Error HRESULT E_FAIL has been returned from a call to a COM component".. arghh...
  5. Krasimir
    Krasimir avatar
    15 posts
    Member since:
    Jan 2011

    Posted 11 Aug 2011 Link to this post

    Check the example in this topic. There is also a tab control with close buttons and the content to each tab control is UserControl. I hope it can help you.
    Specify the Header template with the close button in "<Setter Property="HeaderTemplate">" and the content template here: "<Setter Property="ContentTemplate">"
    Bind the user control like this: <ContentControl Content="{Binding Content}" /> where Content is your user control.
  6. figueiredorj
    figueiredorj avatar
    68 posts
    Member since:
    Mar 2011

    Posted 11 Aug 2011 Link to this post

    I am getting their!

    Thanks for your help.. it really lead the way.

    Got still 2 issues (one just because that I haven't checked if it behaves as it should be expected).

    • when I register the telerik handler

    EventManager.RegisterClassHandler(typeof(TabItemModel), RoutedEventHelper.CloseTabEvent, new RoutedEventHandler(OnCloseClicked));
     I get "Exception of type 'System.ArgumentException' was thrown.".
    my routed event helper:
    using System.Windows;
    using System.Windows.Controls;
    using Telerik.Windows;
     
    namespace DoisSoft.TTrack.TabsControl
    {
     
        public class RoutedEventHelper
        {
            //Create the routed event:
            public static readonly Telerik.Windows.RoutedEvent CloseTabEvent = EventManager.RegisterRoutedEvent(
                "CloseTab",
                RoutingStrategy.Bubble,
                typeof(RoutedEventHandler),
                typeof(RoutedEventHelper));
            //Add an attached property:
            public static bool GetEnableRoutedClick(DependencyObject obj)
            {
                return (bool)obj.GetValue(EnableRoutedClickProperty);
            }
            public static void SetEnableRoutedClick(DependencyObject obj, bool value)
            {
                obj.SetValue(EnableRoutedClickProperty, value);
            }
            // Using a DependencyProperty as the backing store for EnableRoutedClick.
            // This enables animation, styling, binding, etc...
            public static readonly DependencyProperty EnableRoutedClickProperty = DependencyProperty.RegisterAttached(
                "EnableRoutedClick",
                typeof(bool),
                typeof(RoutedEventHelper),
                new System.Windows.PropertyMetadata(OnEnableRoutedClickChanged));
            private static void OnEnableRoutedClickChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
            {
                var newValue = (bool)e.NewValue;
                var button = sender as Button;
                if (button == null)
                    return;
                if (newValue)
                    button.Click += new RoutedEventHandler(OnButtonClick);
            }
            static void OnButtonClick(object sender, RoutedEventArgs e)
            {
                var control = sender as Control;
                if (control != null)
                {
                    control.RaiseEvent(new RadRoutedEventArgs(RoutedEventHelper.CloseTabEvent, control));
     
                }
            }
        }
    }

    So I don't understand what I may be missing. Any clue?

    the other thing is about the isSelected Property. Don't I need to bind it to some property? (I tried to do on xaml
    the following
    <Setter Property="IsSelected" Value="{Binding IsSelected}" />
    but it did caput (I defined the property on viewmodel)
    ). Is the property incorrectly binded or  I should check something else?

    Thanks again

  7. Lilia
    Lilia avatar
    32 posts
    Member since:
    Mar 2011

    Posted 12 Aug 2011 Link to this post

    I had the exact same issue with the IsSelected property so I've done this:

    <Setter Property="IsSelected" Value="True" />
    So every time I've added a new tab it was selected.
    About the RoutedEventHelper I didn't have any problems with it, I just used theirs without any modifications. Here it is:

    public class RoutedEventHelper
        {
            //Create the routed event:
            public static readonly Telerik.Windows.RoutedEvent CloseTabEvent = EventManager.RegisterRoutedEvent(
                "CloseTab",
                RoutingStrategy.Bubble,
                typeof(RoutedEventHandler),
                typeof(RoutedEventHelper));
     
            //Add an attached property:
            public static bool GetEnableRoutedClick(DependencyObject obj)
            {
                return (bool)obj.GetValue(EnableRoutedClickProperty);
            }
     
            public static void SetEnableRoutedClick(DependencyObject obj, bool value)
            {
                obj.SetValue(EnableRoutedClickProperty, value);
            }
     
            // Using a DependencyProperty as the backing store for EnableRoutedClick.
            // This enables animation, styling, binding, etc...
            public static readonly DependencyProperty EnableRoutedClickProperty = DependencyProperty.RegisterAttached(
                "EnableRoutedClick",
                typeof(bool),
                typeof(RoutedEventHelper),
                new System.Windows.PropertyMetadata(OnEnableRoutedClickChanged));
             
            private static void OnEnableRoutedClickChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
            {
                var newValue = (bool)e.NewValue;
                var button = sender as Button;
                if (button == null)
                    return;
                if (newValue)
                    button.Click += new RoutedEventHandler(OnButtonClick);
            }
             
            static void OnButtonClick(object sender, RoutedEventArgs e)
            {
                var control = sender as Control;
                if (control != null)
                {
                    control.RaiseEvent(new RadRoutedEventArgs(RoutedEventHelper.CloseTabEvent, control));
                }
            }
        }

    I register it and create the OnCloseTabClicked event handler like this:

    //Register in the constructor of the class
    EventManager.RegisterClassHandler(typeof(RadTabItem), RoutedEventHelper.CloseTabEvent, new RoutedEventHandler(OnCloseTabClicked));
     
     public void OnCloseTabClicked(object sender, RoutedEventArgs e)
            {
                var tabItem = sender as RadTabItem;
                // Remove the item from the collection the control is bound to
                TabPanes.Remove(tabItem.DataContext as TabItemModel);
            }

    Hope that helps!

    Cheers,
    Lily





Back to Top
DevCraft banner