My last post showed how to setup a TabbedPage with separate View/ViewModels for each tab using Caliburn.Micro. The post used a DataTemplateSelector to resolve the tab content which isn’t the preferred technique when working with Caliburn.Micro. Today we’ll use a strategy that is more aligned to Caliburn’s philosophy and is a tiny bit more extensible.
As per the previous post, we used a DataTemplateSelector because the default TabbedPage.ItemTemplate expects a ContentPage and we wanted to use existing ContentPage items as tabs. In reality, this was a situation that occurred because our team had originally developed these pages independently and then wanted to consolidate them into a TabbedPage after the fact. If you don’t plan on navigating to these pages outside of the TabbedPage, we can build up our ContentPage inside the DataTemplate and use Caliburn.Micro’s binding syntax. This approach will require us to change our existing ContentPage(s) into ContentView(s) and since we depended on the Page objects to provide us with Title and Icon information, we’ll need to push this information into our ViewModels.
Let’s introduce a simple interface for our ViewModels that will be tabs in our TabbedPage:
The changes to the ViewModel are pretty trivial. We simply implement the ITabViewModel interface:
Next, we register our ViewModels in the App using the ITabViewModel signature:
Lastly, we can change our Screen Conductor to be less coupled to the specific ViewModels:
The changes to the view are also very trivial. We’re simply changing them from ContentPage to ContentView. There are a few attributes that aren’t available (Title, Icon) so we’ll simply remove them if present.
And then finally, we can remove our DataTemplateSelector and use the View.Model attached property to resolve our ContentView: