Data for the Xamarin Forms Previewer with Prism
Live preview with design time data is a very important tool in UI development. The Xamarin previewer is pretty nice, but there are some issues when you want to bind ViewModels. The tutorial from James Montemagno post last year gives you a good start for setting a BindingContext for the previewer. There’s just a little fix necessary, that I describe below.
Then, there are some issues that I don’t like that much in the example. One is, that the solution limited to binding a certain ViewModel implementation for design time. And it doesn’t show a solution about how to switch between design- and runtime- viewmodels, depending on the context.
Which leads us to another issue – the fact that there is no built-in flag indicating that the software is running in the previewer. Before, there was a bug that helped: Application.Current was null in the previewer context. But this was fixed, and now this can only be solved with tricks (like described in this post) or by manually un/commenting code sections.
Furthermore, in a real world application, I prefer to solve the design time data in a different way – meaning that I want to use the SAME viewmodel for design- and runtime, but change the underlying dependencies. In a classical MVVM implementation, we inject models and clients into the viewmodel using interfaces. Based on that, we can create 2 different implementations for these dependencies, which could even simulate read/write operations and events or push notifications.
Switching between the 2 type registrations for dependency injection can still happen manually (I prefer this over using tricks), or automatically when there’s a good built-in solution for knowing the context we’re in.
However, I want to show the 2 different ways of binding a context to the UI: the one based on James Montemagno’s post, and the one using DI with Prism.
Direct BindingContext in xaml
There’s not too much to add to James Montemagno’s post. Just that the syntax of the BindingContext in xaml from the original post doesn’t work (anymore?). Instead, I could solve it like that:
DependencyInjection with Prism’s ViewModelLocator
If using the BindingContext from the previous example, the automatic binding through the Locator wouldn’t work. But it’s working perfectly with the PrismApplication and Injection – the RegisterTypes() function is being called on loading of the Previewer. I’m using Unity, but it should be the same behaviour for any DI framework. Just remember that you’ll probably have to reload VisualStudio after making significant changes to the DI setup.
For simplicity, I just use a flag to distinguish between design- and runtime for now. Don’t forget that if your application is using platform specific implementations (IPlatformInitializer), you’ll have to provide design time implementations in the ‘design’ section – if they’re necessary for constructing ViewModels.
Be aware that you have to define the default constructor, although the parameter of the second constructor has a default value. For the Xamarin Previewer, that’s not enough. If a default constructor was missing, and the previewer is in the state of error, you’ll have to clean, close VS, and I recommend to delete all obj/debug folders. Then on restart, build all and it should be fine.
So now everything should be fine, to use ViewModels with injected dependencies in the Previewer. The only problem that I have left is, that the iOS renderer cannot startup the PrismApplication – a problem with resolving the signature of the virtual method ‘Initialize’. The same thing works perfectly find for Android, so I expect it has to do with the iOS Mono implementation. I hope someone has a solution for that.
The previewer makes a very good job rendering the UI for the different platforms. But there are still flaws about refresh/stability and diagnostic capabilities.
When the application didn’t start up properly – for example because of the missing default constructor, the previewer doesn’t really recover.
For previewing screens on iOS, you should avoid using Prism and Dependency Injection, and go the hard coded way, assigning the BindingContext in xaml. Other solutions with ViewModelLocator would probably work, but I didn’t get into that yet.
Once using a bit more complex solution for design time data – meaning viewmodel logic, mocked services and events – I soon started wishing to have debug capabilities for that. When I was developing UIs with xaml and WPF in VisualStudio, there was a pretty good solution for it – just open up another instance of VisualStudio with the same solution, and attach the debugger to the designer process of the other VisualStudio instance. Then you could debug the ViewModels when the WPF designer refreshes. But in this case, the application runs probably on the Mac, I’m just not quite sure what about the Android rendering.
So – as a final conclusion, I would just like to ask Xamarin for a few things regarding the Previewer
- Really reset/reload the application when closing/opening the previewer
- Provide a flag to programmatically distinguish between design- and runtime
- Provide a solution to debug ViewModel’s in the Previewer context