Why is my Child View not displayed when I show my Container View in the MainWindow with WPF ReactiveUI?

huangapple go评论63阅读模式
英文:

Why is my Child View not displayed when I show my Container View in the MainWindow with WPF ReactiveUI?

问题

在主窗口中显示ContainerView时,ChildView未显示的原因可能是模板(ControlTemplate)中的问题。你的模板设置如下:

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="views:ContainerView">
            <Grid>
                <reactiveUi:ViewModelViewHost x:Name="Child"></reactiveUi:ViewModelViewHost>
            </Grid>
        </ControlTemplate>
    </Setter.Value>
</Setter>

在这个模板中,你使用了ViewModelViewHost来托管Child视图模型,但你没有在ViewModelViewHost中定义具体的视图。要显示ChildView,你需要在这个模板中添加ChildView控件。可以尝试将ChildView添加到ViewModelViewHost中,如下所示:

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="views:ContainerView">
            <Grid>
                <reactiveUi:ViewModelViewHost x:Name="Child">
                    <views:ChildView />
                </reactiveUi:ViewModelViewHost>
            </Grid>
        </ControlTemplate>
    </Setter.Value>
</Setter>

这将在ViewModelViewHost中显示ChildView,并且ChildView的样式应该正常工作。希望这可以解决问题。

英文:

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&lt;ContainerViewModel&gt;
{
    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 =&gt; ViewModel;
        set =&gt; ViewModel = (ContainerViewModel)value;
    }

    public ContainerView()
    {
        this.WhenActivated(d =&gt;
        {
            this.OneWayBind(ViewModel, vm =&gt; vm.Child, view =&gt; 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 =&gt; _child;
        
         set =&gt; this.RaiseAndSetIfChanged(ref _child, value);
    
     }
 
    

     public ContainerViewModel()
    {
        
         Child = new ChildViewModel();
    
     } 

}

&lt;Style TargetType=&quot;{x:Type views:ContainerView}&quot;&gt;
    &lt;Setter Property=&quot;Template&quot;&gt;
        &lt;Setter.Value&gt;
            &lt;ControlTemplate TargetType=&quot;views:ContainerView&quot;&gt;
                &lt;Grid&gt;
                    &lt;reactiveUi:ViewModelViewHost x:Name=&quot;Child&quot;&gt;&lt;/reactiveUi:ViewModelViewHost&gt;
                &lt;/Grid&gt;
            &lt;/ControlTemplate&gt;
        &lt;/Setter.Value&gt;
    &lt;/Setter&gt;
&lt;/Style&gt;

And here's the code for the "ChildView" and its style:

public class ChildView : Control, IViewFor&lt;ChildViewModel&gt;
{
    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 =&gt; ViewModel;
        set =&gt; ViewModel = (ChildViewModel)value;
    }

    public ChildView()
    {
        DefaultStyleKey = nameof(ChildView);
    }
}


&lt;Style TargetType=&quot;{x:Type views:ChildView}&quot;&gt;
    &lt;Setter Property=&quot;Background&quot; Value=&quot;Brown&quot;&gt;&lt;/Setter&gt;
    &lt;Setter Property=&quot;Template&quot;&gt;
        &lt;Setter.Value&gt;
            &lt;ControlTemplate TargetType=&quot;views:ChildView&quot;&gt;
                &lt;Ellipse Width=&quot;200&quot; Height=&quot;200&quot; Fill=&quot;Yellow&quot; &gt;&lt;/Ellipse&gt;
            &lt;/ControlTemplate&gt;
        &lt;/Setter.Value&gt;
    &lt;/Setter&gt;
&lt;/Style&gt;

Any idea why the ChildView is not displayed?

答案1

得分: 0

Ok, 我明白了.. 我不确定这是否是最佳解决方案,但对我来说有效。我必须自己在 View 中实例化 ViewModel。

public ContainerView()
{
    this.ViewModel = new ContainerViewModel();
    this.WhenActivated(d =>
    {
        this.OneWayBind(ViewModel, vm => vm.Child, view => view.Child.ViewModel);
    });
}
英文:

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 =&gt;
    {
        this.OneWayBind(ViewModel, vm =&gt; vm.Child, view =&gt; view.Child.ViewModel);
    });
}

huangapple
  • 本文由 发表于 2023年2月14日 18:59:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/75446864.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定