WPF 中的 ReactiveUI:RoutedViewHost 无法解析视图
ReactiveUI in WPF: RoutedViewHost Can't Resolve View
我最近接受了学习如何在 WPF 中构建应用程序的任务,并将 ReactiveUI 作为我的 MVVM 框架。我目前正在尝试在我的应用程序中练习实现路由器,我发现尽管遵循了“你、我和 ReactiveUI”中的示例,但我的 RoutedViewHost 没有显示视图,并抛出错误:
"System.Exception:'无法找到 'LearnReactiveUI.ViewModels.StartupViewModel' 的视图。'""
下面是我的主要 window (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 class,它创建了一个 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 的代码隐藏,它将 Router 绑定到 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);
});
}
}
}
我的 Startup 视图的代码也很简单。这是 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
设置应该在 bootstrap-like class 中完成,以允许多平台编码并且不破坏 DI。学基础的时候应该看看这个
我最近接受了学习如何在 WPF 中构建应用程序的任务,并将 ReactiveUI 作为我的 MVVM 框架。我目前正在尝试在我的应用程序中练习实现路由器,我发现尽管遵循了“你、我和 ReactiveUI”中的示例,但我的 RoutedViewHost 没有显示视图,并抛出错误:
"System.Exception:'无法找到 'LearnReactiveUI.ViewModels.StartupViewModel' 的视图。'""
下面是我的主要 window (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 class,它创建了一个 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 的代码隐藏,它将 Router 绑定到 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);
});
}
}
}
我的 Startup 视图的代码也很简单。这是 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
设置应该在 bootstrap-like class 中完成,以允许多平台编码并且不破坏 DI。学基础的时候应该看看这个