I have a wpf application using Caliburn.Micro 2.0.1 and I found strange behaviour of Caliburn.Micro. In latest 3.0.3 it exists too.
Super simple project to reproduce bug: https://github.com/ihtfw/CaliburnMicroBug
MainWindowViewModel is Conductor for Screens. There are two ScreenViewModel as Items for MainWindowViewModel with property SingletonViewModel. In MainViewModel I can switch to first ScreenViewModel or second one.
Everything works perfect except that View for SingletonViewModel is shown only on Second ScreenViewModel after switching to second screen.
To reproduce:
How to fix this?
Update
It's not possible to make these with ContentControl. Should use explicit view. In this case SingletonView and set DataContext of it. To wire up Caliburn.Micro actions bind them without context. So result will be:
<local:SingletonView DataContext={Binding Path=SingletonViewModel} cal:Action.TargetWithoutContext="{Binding}" />
As stated in the other answers you cannot have a "singleton view", the xaml UI model will not allow the same UI elements to be in the visual tree twice.
What you can do however is have two instances of the same view bound to the view model.
To do this you'll need to sidestep a feature of the framework.
Internally any view model which implements IViewAware holds a weak reference to the view, any time the framework tries to locate the view for a view model it first queries to the view model for that reference.
If a reference is returned then the view is removed from it's existing location and inserted into the new location.
In order to stop this can you do one of three things:
SingletonViewModel not inherit from something that implements IViewAware such as PropertyChangedBase.ViewLocator.LocateForModel to remove this behavior with the second code sample below.Hacky null out view
protected override void OnViewAttached(object view, object context)
{
Views[context ?? ViewAware.DefaultContext] = null;
}
Remove IViewAware behavior
ViewLocator.LocatorForModel = (model, location, context) => ViewLocator.LocateForModelType(model.GetType(), location, context);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With