【问题标题】:Select which view to display when Main Window open in Prism选择在 Prism 中打开主窗口时要显示的视图
【发布时间】:2017-06-15 23:17:43
【问题描述】:

这确实应该很容易,但我无法确定它。
我有 Prism 6 的小型 WPF 应用程序
我有主窗口和里面的两个视图。

MainWindowMainWindowViewModel 视图模型类
ConfigurationViewConfigurationViewModel 视图模型类
SignInViewSignInViewModel 视图模型类

现在第一次显示主窗口时,我想根据一些布尔条件选择要显示的视图

这是bootstrap 类的sn-p。

protected override void ConfigureViewModelLocator()
{
    base.ConfigureViewModelLocator();

    ViewModelLocationProvider.Register<MainWindow, MainWindowViewModel>();
    ViewModelLocationProvider.Register<SignInView, SignInViewModel>();
    ViewModelLocationProvider.Register<ConfigurationView, ConfigurationViewModel>();

    Container.RegisterInstance(new SignInView());
    Container.RegisterInstance(new ConfigurationView());
}

protected override DependencyObject CreateShell()
{
    return Container.Resolve<MainWindow>();
}

protected override void InitializeShell()
{
    Application.Current.MainWindow.Show();

    IRegionManager _regionManager = Container.Resolve<IRegionManager>();
    IRegion _region = _regionManager.Regions[RegionNames.MainRegion];

    _region.Add(Container.Resolve<SignInView>());
    _region.Add(Container.Resolve<ConfigurationView>());
}

现在打开应用程序的主窗口时总是显示SignInView
如何根据某些条件选择要显示的视图需要从MainWindowViewModel 类中引入

更新

public class MainWindowViewModel
{
    private IAccountService _accountService;

    public MainWindowViewModel(IUnityContainer container)
    {
        IRegionManager regionManager = Container.Resolve<IRegionManager>();
        _accountService = container.Resolve<IAccountService>();

        if (_accountService.IsSignedIn)
            regionManager.RequestNavigate(RegionNames.MainRegion, new Uri(nameof(ConfigurationView), UriKind.Relative));
        else
            regionManager.RequestNavigate(RegionNames.MainRegion, new Uri(nameof(SignInView), UriKind.Relative));
    }       
}

主窗口视图

<Window x:Class="Shell.Views.MainWindow"
        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:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True">

此代码不起作用。

【问题讨论】:

  • @mm8 你能举个例子吗
  • @mm8 我更新了我的问题
  • @mm8 并把它们放在MainWindowViewModel的构造函数中吧?
  • 您的 MainWindowViewModel 是在哪里创建的,您在其构造函数中使用的“RegionManager”是什么?
  • @mm8 所有视图模型都是通过设置每个视图的prism:ViewModelLocator.AutoWireViewModel="True"属性自动创建的。

标签: c# wpf prism


【解决方案1】:

需要先创建区域,然后才能向其添加视图。因此,您最好在创建MainWindow 之后自己创建MainViewModel

protected override void ConfigureViewModelLocator()
{
    base.ConfigureViewModelLocator();

    ViewModelLocationProvider.Register<SignInView, SignInViewModel>();
    ViewModelLocationProvider.Register<ConfigurationView, ConfigurationViewModel>();

    Container.RegisterInstance(new SignInView());
    Container.RegisterInstance(new ConfigurationView());
}

protected override DependencyObject CreateShell()
{
    return Container.Resolve<MainWindow>();
}

protected override void InitializeShell()
{
    IRegionManager _regionManager = Container.Resolve<IRegionManager>();
    IRegion _region = _regionManager.Regions[RegionNames.MainRegion];

    _region.Add(Container.Resolve<SignInView>());
    _region.Add(Container.Resolve<ConfigurationView>());


    var mainWindowViewModel = Container.Resolve<MainWindowViewModel>();
    Application.Current.MainWindow.DataContext = mainWindowViewModel;
    Application.Current.MainWindow.Show();
}

MainWindow 中删除它:

prism:ViewModelLocator.AutoWireViewModel="True">

【讨论】:

  • 以下语句IRegion _region = _regionManager.Regions[RegionNames.MainRegion]; 抛出异常:“区域管理器不包含 MainRegion 区域。”
  • 感谢这有效,但我希望我仍然可以使用prism:ViewModelLocator.AutoWireViewModel="True"
  • 为什么?这通常被认为是一种反模式,在这种情况下它甚至不起作用。视图需要在视图模型使用它之前创建区域,但是当使用视图模型定位器创建视图模型时,视图模型被创建,因此它的构造函数被执行,甚至在区域存在之前。也许您应该考虑在模块中调用 RegisterViewWithRegion 方法,并从驻留在实际模块中的视图模型导航到视图。或者您可以简单地自己创建 MainWindowViewModel。
  • @mm8 实际上,Prism 的 ViewModelLocator 不是反模式,因为它不是真正的 ViewModelLocator,因为它是一个静态类,它包含代表应用程序中每个 VM 的属性。它使用约定来发现并创建虚拟机,这不是反模式,仍然使用 DI。
  • 还不错,Brian,但这并不意味着无论如何你都必须使用它来创建视图模型 :) 在这种情况下,最好不要使用它。
【解决方案2】:

首先,注册导航的视图类型,而不是视图实例。

其次:条件 - 或更笼统地说:数据 - 很少来自视图模型(除非它是用户输入),因此您应该有一些 IUserManagement 服务来拉出当前用户。

话虽如此,如果您注册了视图,您应该能够导航到它。如果没有具体的例外,很难猜出哪里出了问题。

Container.RegisterTypeForNavigation<SignInView>();

...

_regionManager.RequestNavigate( RegionNames.MainRegion, typeof(SignInView).Name );

【讨论】:

  • 引导程序的ConfigureContainer(或您的模块的Initialize)中的第一行,无论您想导航到登录视图的哪个位置,都是第二行。我猜我会把它放在引导程序InitializeModules 的末尾。
猜你喜欢
  • 2023-02-17
  • 2017-06-09
  • 1970-01-01
  • 2019-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-03
  • 2023-03-11
相关资源
最近更新 更多