Silverlight TabControl with deletable TabItems

Topics: UI Architecture
Jun 27, 2011 at 3:18 PM

Hi guys,
I would like to have a Silverlight application that works like a Browser with Tabs but in the Silverlight application. Not oppening a new tab in the browser!!
If u click a item in the menue, a new Tab in the TabControl will open with the corresponding View.

For that I created a ActionBehavior like this:

    public class AddTabToTabControlAction : TargetedTriggerAction<TabControl>

        private TabControl tabControl;

        #region NewViewModelProperty

        public static readonly DependencyProperty NewViewModelProperty = DependencyProperty.Register("NewViewModel",
            typeof(IScreen), typeof(AddTabToTabControlAction), null);

        public IScreen NewViewModel
            get {
                return (IScreen)base.GetValue(NewViewModelProperty);
            set {
                base.SetValue(NewViewModelProperty, value);

        protected override void OnAttached()
            tabControl = (TabControl)(this.AssociatedObject);

        protected override void OnDetaching()

        protected override void Invoke(object parameter)
            if (NewViewModel != null) { 
                //see if the viewmodel is already added
                var tab = (from tabs in tabControl.Items.Cast<TabItem>()
                           where (tabs.Tag as string) == NewViewModel.DisplayName
                           select tabs).FirstOrDefault();

                if (tab == null) {


                else {  // Tab already exists
                    // Set the Tab as selected
                    tab.IsSelected = true;

        private void AddTabToTabControl()
            TabItem tabItem = new TabItem()
                Tag = NewViewModel.DisplayName

            // ** Tab Content **
            var viewContent = LocateViewFor(NewViewModel);

            ViewModelBinder.Bind(NewViewModel, tabItem, null);
            tabItem.Content = viewContent; //TODO: can this be done by xaml caliburn.View

            // ** Tab Header **
            TabHeaderViewModel headerViewModel = new TabHeaderViewModel()
                HeaderDisplay = NewViewModel.DisplayName,
                TabItem = tabItem,
                TabControl = tabControl

            var viewHeader = LocateViewFor(headerViewModel);
            ViewModelBinder.Bind(headerViewModel, tabItem, null);
            tabItem.Header = viewHeader;

            tabItem.IsSelected = true;

        private object LocateViewFor(object viewModel)
            var view = ViewLocator.LocateForModelType(viewModel.GetType(), nullnull);
            return view;


        <sdk:TabControl x:Name="Tab" 
                        <ei:PropertyChangedTrigger Binding="{Binding NewViewModel, Mode=OneWay}">
                            <behaviors:AddTabToTabControlAction NewViewModel="{Binding NewViewModel, Mode=OneWay}"/>

The problem is the Binding ViewModel with View. If I click something in the new view. The action comes not to the ViewModel.

Please help!!
Jun 27, 2011 at 5:12 PM

I couldn't figure out the problem... the binding code seems OK.
If you could put together a small repro, that would really help me to understand the cause.

There is a reason why you chose the behavior approach?
This scenario could be well addressed using model-first for the entire tab, not just for its pages.
Have a look at the SimpleMDI sample in the source code: the scenario should be very similar to yours, and it is implemented using a Conductor.Collection.OneActive (a VM representing a set of child VMs).

Jun 28, 2011 at 8:20 AM

thx for your answer!!
The problem is the red colored part with the binding. Unfortunatly just the last binding does work. I dont know why. Even I dont know why I have to bind the ViewModel with the TabItem.
Why I have chosen a behavior? Because in this code I have the TabControl and the TabItem in access. I wanna delete the TabItem from the TabControl as well. So I give these information to the TabHeaderViewModel.

Your example is pretty good. But It doesnt worke in Silverlight. So I looked for another example and I found this article:

In this is written this paragrath:

Rebuild this sample in Silverlight. Unfortunately, Silverlight’s TabControl is utterly broken and cannot fully leverage databinding. Instead, try using a horizontal ListBox as the tabs and a ContentControl as the tab content. Put these in a DockPanel and use some naming conventions and you will have the same affect as a TabControl.

But I have no ideer how i should work with a ListBox?
Maybe u can give me the xaml?

Thank you for your help!!

Jun 28, 2011 at 7:21 PM
Edited Jun 28, 2011 at 7:23 PM

It should be something along this path (assuming the VM is a Conductor<>.Collection.OneActive):


		<RowDefinition Height="auto" />
		<RowDefinition Height="*" />
	<!-- tabs -->
	<ListBox Name="Items" Grid.Row="0">
				<!-- template of tab header -->
				<Border ...>
					<TextBlock Text="{Binding DisplayName}" />
					<!-- configuration of panel holding the various tab header; lays out item horizontally -->
					<StackPanel Orientation="Horizontal" />

	<!-- active item area -->
	<ContentControl Name="ActiveItem" Grid.Row="1" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" />

(sorry for possible errors, I'm writing without VS)