Reputation: 33
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}" />
Upvotes: 3
Views: 487
Reputation: 10609
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);
Upvotes: 4
Reputation: 2875
That is not a Bug.
A UIElement
such as a UserControl
can only have one logical parent.
You are creating two ScreenViews
, and you are trying to add the same SingletonView
to both of them, which is not possible, because SingletonView
cannot have two parents.
Upvotes: 0
Reputation: 543
I've worked on your project and found out that your problem is in MainWindows constructor. Change MainWindow's constructor like below:
public MainWindowViewModel()
{
Items.Add(new ScreenViewModel
{
DisplayName = "Screen 1",
SingletonViewModel = new SingletonViewModel()
});
Items.Add(new ScreenViewModel
{
DisplayName = "Screen 2",
SingletonViewModel = new SingletonViewModel()
});
ActiveItem = Items.First();
}
Upvotes: 0