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

Close Button on TabControl... again!

5 Answers 124 Views
TabControl
This is a migrated thread and some comments may be shown as answers.
figueiredorj
Top achievements
Rank 1
figueiredorj asked on 11 Aug 2011, 11:48 AM
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.

5 Answers, 1 is accepted

Sort by
0
Lilia
Top achievements
Rank 1
answered on 11 Aug 2011, 01:12 PM
Have you seen the Telerik online help for adding a close button? It worked like a charm for me.
0
figueiredorj
Top achievements
Rank 1
answered on 11 Aug 2011, 04:35 PM
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...
0
Krasimir
Top achievements
Rank 1
answered on 11 Aug 2011, 04:53 PM
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.
0
figueiredorj
Top achievements
Rank 1
answered on 11 Aug 2011, 06:20 PM
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

0
Lilia
Top achievements
Rank 1
answered on 12 Aug 2011, 07:51 AM
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





Tags
TabControl
Asked by
figueiredorj
Top achievements
Rank 1
Answers by
Lilia
Top achievements
Rank 1
figueiredorj
Top achievements
Rank 1
Krasimir
Top achievements
Rank 1
Share this question
or