Unexpected behaviour using TabControl

Jul 16, 2010 at 4:00 PM
Edited Jul 19, 2010 at 8:42 AM

While learning how to use Caliburn.Micro properly, I wrote a simple application that uses a TabControl, and experienced an unexpected behaviour, at least for me.

The Shell of my test application contains a TabControl, used to host the views of Modules (for the sake of simplicity let's consider them view-models) loaded at runtime. To be more specific, the view-model of the Shell exposes a Modules property of type ObservableCollection<IViewModelModule> (IViewModelModule is just a dummy interface used to identify view-model loaded at runtime). The Shell view has a TabControl named Modules which, in my intentions, should contain the views associated to the Modules/view-models.

That said, given the default convention, Caliburn.Micro properly binds the collection to TabControl.ItemsSource, unfortunally the specified view is applied to TabItem.Header, instead of TabItem.Content.

I think that the behavior is caused by the ConventionManager.DefaultDataTemplate, which is applied to the TabControl.ItemTemplate, that controls the TabControl.Header template, while it should be probably set to the TabControl.ContentTemplate.

Of course, I know that I could change the default implementation of Caliburn.Micro.ConventionManager.AddCustomBindingBehavior to implement a proper logic, but my question is: how can I 'violate' the default rule for this specific scenario? Is there a view-only/Xaml-only/Caliburn-ish way to achieve the expected result?

A simple project exploiting the issue can be found here.

Jul 16, 2010 at 4:03 PM

Is this WPF or SL?

Jul 17, 2010 at 9:02 AM
It is WPF, I haven't tested the Silverlight behaviour.
Jul 19, 2010 at 4:39 PM
Edited Jul 19, 2010 at 4:39 PM

I performed a test on a Silverlight project. The result is different, but unfortunally it is still no good.

I duplicated the code from the previous WPF test application (avoiding the runtime loading), so I still have a Shell with a TabControl used to host views (at the moment I have 2 dummy views). In this case, the method Caliburn.Micro.ViewModelBinder.BindProperties() raises an exception:

Unable to cast object of type 'TestApplicationSL.ViewModels.FirstViewModel' to type 'System.Windows.Controls.TabItem'.

while performing the Binding between the collection of view-models and the TabControl.ItemsSoruce property.

As you can probably guess, the TabControl does not wrap the object with a TabItem automatically… which is a bug of the SL TabControl.

So, in this case I cannot take advantage of the Caliburn.Micro convention mechanism.

An updated version of the test solution (where I failed to circumvent the TabControl issue, due to SL limitations when it comes to reflection) can be found here.


Jul 19, 2010 at 4:43 PM
I know how to fix this for the WPF version, just haven't got around to it yet...Lot's of stuff going on right now. I'll try to get to is soon. Unfortunately, it's not fixable for Silverlight because their Tab control is a piece of junk...and they still haven't fixed it...
Jul 19, 2010 at 5:31 PM
Edited Jul 19, 2010 at 5:32 PM

May I ask you how you intend to fix this? Because, to be honest, after investigating the problem in depth, I don't think it can be considered a framework issue.

The TabControl itself uses a 'convention' regarding the ItemTemplate (applied to the header) that does not get along well with the Caliburn.Micro convention, but that doesn't mean that Caliburn.Micro should cope with the issue by default. There could be plenty of cases where something like this could happen, that's why I asked what was the 'proper' way to solve it: is changingCaliburn.Micro.ConventionManager.AddCustomBindingBehavior the proper way to address the issue? What kind of alternatives does Caliburn.Micro offer?

Regarding the Silverligh issue... well, I don't really use it, but I can finally understand the frustration of people that have to deal with its missing features from the beginning...

Aug 31, 2010 at 2:50 AM

Does anyone have any update on this? I'm having the same problem as that faced by BladeWise. BTW I'm new to Caliburn family.

Aug 31, 2010 at 12:31 PM

Changing ConventionManager.AddCustomBindingBehavior is probably the best way to handle this. I'm considering some improvements to the way this extensibility point works. So, if you make a fix, be on the lookout for a change in this in the next couple of weeks.

Sep 13, 2010 at 5:17 AM

Is there an update on this yet to fix it for the WPF TabControl? Or could you provide any further help as to what you mean by changing ConventionManager.AddCustomBindingBehavior to handle it?

Sep 13, 2010 at 11:54 AM

I'm going to try and get this fixed today :)

Sep 13, 2010 at 7:58 PM

I believe I have now fixed this issue as of revision 3167da8f7cbc