I am currently learning my way around WPF and ReactiveUI. I try to explain my problem with a simplified example. I have a ContainerView that contains a ChildView and is bound to a ContainerViewModel. The ContainerViewModel has a property Child that is bound to the ChildView control. The ChildView control has a corresponding ChildViewModel.
I also have a style for my ContainerView that sets the Template property to a ControlTemplate with a Grid that contains a ViewModelViewHost control named "Child".
However, when I show the ContainerView in the MainWindow, the ChildView is not displayed.
Here's the code for the ContainerView/ViewModel and its style:
public class ContainerView : Control, IViewFor<ContainerViewModel>
{
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
nameof(ViewModel), typeof(ContainerViewModel), typeof(ContainerView), new PropertyMetadata(default(ContainerViewModel)));
public ContainerViewModel ViewModel
{
get { return (ContainerViewModel)GetValue(ViewModelProperty); }
set { SetValue(ViewModelProperty, value); }
}
object? IViewFor.ViewModel
{
get => ViewModel;
set => ViewModel = (ContainerViewModel)value;
}
public ContainerView()
{
this.WhenActivated(d =>
{
this.OneWayBind(ViewModel, vm => vm.Child, view => view.Child.ViewModel);
});
}
private ViewModelViewHost Child { get; set; }
public override void OnApplyTemplate()
{
Child = GetTemplateChild(nameof(Child)) as ViewModelViewHost;
}
}
public class ContainerViewModel : ReactiveObject
{
private ChildViewModel _child;
public ChildViewModel Child
{
get => _child;
set => this.RaiseAndSetIfChanged(ref _child, value);
}
public ContainerViewModel()
{
Child = new ChildViewModel();
}
}
<Style TargetType="{x:Type views:ContainerView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="views:ContainerView">
<Grid>
<reactiveUi:ViewModelViewHost x:Name="Child"></reactiveUi:ViewModelViewHost>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here's the code for the "ChildView" and its style:
public class ChildView : Control, IViewFor<ChildViewModel>
{
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
nameof(ViewModel), typeof(ChildViewModel), typeof(ChildView), new PropertyMetadata(default(ChildViewModel)));
public ChildViewModel ViewModel
{
get { return (ChildViewModel)GetValue(ViewModelProperty); }
set { SetValue(ViewModelProperty, value); }
}
object? IViewFor.ViewModel
{
get => ViewModel;
set => ViewModel = (ChildViewModel)value;
}
public ChildView()
{
DefaultStyleKey = nameof(ChildView);
}
}
<Style TargetType="{x:Type views:ChildView}">
<Setter Property="Background" Value="Brown"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="views:ChildView">
<Ellipse Width="200" Height="200" Fill="Yellow" ></Ellipse>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Any idea why the ChildView is not displayed?
Ok, I think i got it.. I don't no if this is the best solution, but it works for me. I had to instantiate the ViewModel in the View by myself.
public ContainerView()
{
this.ViewModel = new ContainerViewModel();
this.WhenActivated(d =>
{
this.OneWayBind(ViewModel, vm => vm.Child, view => view.Child.ViewModel);
});
}