微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

WPF 中的 ReactiveUI:RoutedViewHost 无法解析视图

如何解决WPF 中的 ReactiveUI:RoutedViewHost 无法解析视图

我最近开始学习如何在 WPF 中构建应用程序,并使用 ReactiveUI 作为我的 MVVM 框架。我目前正在尝试在我的应用程序中练习实现路由器,我发现尽管遵循了“你、我和 ReactiveUI”中的示例,但我的 RoutedViewHost 没有显示视图,并抛出错误

"System.Exception: '找不到'LearnReactiveUI.viewmodels.Startupviewmodel'的视图。'"

下面是我的主窗口 (ReactiveWindow) 的 xaml,并有一个 RoutedViewHost 作为它的主体

<rxui:ReactiveWindow x:Class="LearnReactiveUI.Views.MainView"
        xmlns:rxui="http://reactiveui.net"
        xmlns:vms="clr-namespace:LearnReactiveUI.viewmodels"
        x:TypeArguments="vms:Mainviewmodel"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:LearnReactiveUI.Views"
        mc:Ignorable="d"
        Title="MainView" Height="450" Width="800">
    <Grid>
        <rxui:RoutedViewHost x:Name="routedViewHost"/>
    </Grid>
</rxui:ReactiveWindow>

这是我的 Mainviewmodel 类,它创建了一个 RoutingState,然后导航到一个新的 Startupviewmodel

using ReactiveUI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LearnReactiveUI.viewmodels
{
    public class Mainviewmodel : ReactiveObject,IScreen
    {
        private readonly RoutingState routingState;
        public Mainviewmodel()
        {
           this.routingState = new RoutingState();

           routingState.Navigate.Execute(new Startupviewmodel(this));
        }
        public RoutingState Router => this.routingState;
    }
}

最后这里是我的 MainWindow 的代码隐藏,它将路由器绑定到 RoutedViewHost

using ReactiveUI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using LearnReactiveUI.viewmodels;
using System.Reactive.disposables;

namespace LearnReactiveUI.Views
{
    public partial class MainView : ReactiveWindow<Mainviewmodel>
    {
        public MainView()
        {
            InitializeComponent();
            this.viewmodel = new Mainviewmodel();
            this.WhenActivated(disposables =>
                {
                    this
                        .OneWayBind(this.viewmodel,vm => vm.Router,v => v.routedViewHost.Router)
                        .disposeWith(disposables);
                });
        }
    }
}

我的启动视图的代码也非常简单。这是xaml

<rxui:ReactiveUserControl x:Class="LearnReactiveUI.Views.StartupView"
             xmlns:rxui="http://reactiveui.net"
             xmlns:vms="clr-namespace:LearnReactiveUI.viewmodels"
             x:TypeArguments="vms:Startupviewmodel"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:LearnReactiveUI.Views"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Label Content="Startup" HorizontalAlignment="Center"
                   VerticalAlignment="Center" FontSize="72"/>
    </Grid>
</rxui:ReactiveUserControl>

这是 Startupviewmodel 的代码

using ReactiveUI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LearnReactiveUI.viewmodels
{
    public class Startupviewmodel : ReactiveObject,IRoutableviewmodel
    {
        private IScreen hostScreen;
        public Startupviewmodel(IScreen hostScreen)
        {
            this.hostScreen = hostScreen;
        }
        public string UrlPathSegment => "Startup";
        public IScreen HostScreen => this.hostScreen;

    }
}

后面的代码中没有代码,因为我还没有绑定到视图的属性

我的代码编译成功并且我已经验证它会成功实例化 MainView 和 Mainviewmodel。我想弄清楚我哪里出错了。

感谢任何帮助。谢谢!

解决方法

您需要注册您的视图和视图模型。请看routing example

在我看来,MainViewModel 构造函数中的这一更改应该可以解决问题:

public MainViewModel()
{
    this.routingState = new RoutingState();

    // register view and viewModel
    Locator.CurrentMutable.Register(() => new StartupView(),typeof(IViewFor<StartupViewModel>));

    routingState.Navigate.Execute(new StartupViewModel(this));
}

@Glenn Watson 提到了一件重要的事情。 Locator 设置应该在类似引导程序的类中完成,以允许多平台编码并且不会破坏 DI。学基础的时候应该看看这个。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。