I have a Parent and Child viewmodel:
public class ParentViewModel : Screen
{
public ChildViewModel Child { get; set; }
}
public class ChildViewModel : PropertyChangedBase, IChild { }
When the Parent VM is displayed using Conductor.ActivateItem()
, Caliburn.Micro does the usual labours of searching through the view model object graph and looking for views to display etc.
After all this is completed, I find that while ParentViewModel.Parent
is a reference to the Conductor, ChildViewModel.Parent
is null
.
Is this by design?
Many thanks in advance.
Yes this is by design, the method that sets the Parent
property is EnsureItem
in the ConductorBase
, therefore it's only conductors that will set it when the active item is changed.
The Parent
is therefore also only available in the activation life cycle of the child, e.g. OnInitialise
or OnActivate
etc.
Is there any reason your ParentViewModel
isn't a Conductor
type and your ChildViewModel
a Screen?
Also, depending on the Parent
property may be introducing coupling in your ChildViewModel
.
One workaround for this is for the parent VM to pass itself to the child VM somehow.
Either by setting the Parent
property explicitly:
var child = new ChildViewModel
{
Parent = this
};
Or, assuming you have some sort of IoC-based abstraction for initialising view model objects, you could have a convention of implementing Configure()
methods that return this
:
public class ChildViewModel : PropertyChangedBase, IChild
{
// IChild members...
public ChildViewModel Configure(IScreen parent)
{
Parent = parent;
return this;
}
}
public class ParentViewModel : Screen
{
public ChildViewModel Child { get; set; }
protected override void OnInitialize()
{
Child = _viewModelFactory.Create<ChildViewModel>()
.Configure(this);
}
}
It should be possible to customise Caliburm.Micro's view model handling code to set the parent automatically, but I'm not clever enough with it yet to know how to do that, yet. :)