首页 > 解决方案 > 主窗口之前的 WPF PRISM 7 登录窗口

问题描述

我是 WPF/Prism 的新手,我正在尝试执行以下操作:我需要在启动主窗口之前加载登录视图(窗口或用户控件)。成功登录后,删除登录视图并转到 Main Mindow。

我在这里查看了几个答案,但所有答案都在使用 boostrapper 类引用旧版本的 PRISM。

我有一个 WPF (Prism 7) 应用程序,其中包含主项目和一个授权模块。

从我的主项目 App.xaml.cs

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

 protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
 {
    moduleCatalog.AddModule<AuthorizationModule>();
 }

在授权模块中,我有我的 LoginView / LoginViewModel。授权模块注册一个 LoginService 将被注入到 LoginViewModel

public void RegisterTypes(IContainerRegistry containerRegistry)
{
   containerRegistry.Register(typeof(ILoginService), typeof(LoginService));
}

LoginViewModel 将负责使用此 LoginService 对用户进行身份验证。

我看到的部分答案显示如下:

protected override void InitializeShell()
{
    Window login = new LoginView();
    var loginVM = new LoginViewModel(new LoginAuth());
    loginVM.LoginCompleted += (sender, args) =>
    {
        login.Close();
        Application.Current.MainWindow.Show();
    };
    login.DataContext = loginVM;
    // problem below:
    login.ShowDialog();
}

但是,这似乎有点不必手动实例化 LoginView 而不是让容器为您做这件事。

此外,PRISM 7 上的 InitiallizeShell 期望创建当前的 shell。我不确定是否应该使用传递给激活主窗口的这个值。

 protected override void InitializeShell(Window shell)

我还在 Github 上阅读了 Brian Lagunas 本人的文章,可能会使用 EventAggregator(我已经尝试过)。我已经让授权模块注册了 EventAggregator 并从 LoginViewModel 成功登录后,发布了 SuccessLoginEvent 但我可以弄清楚如何从主应用程序订阅该事件

所以基本上预期的结果是,当应用程序启动时,如果用户未登录,则显示 LoginView,在用户对其进行身份验证后,将他带到已加载所有需要的模块的 MainWindow。

任何帮助将不胜感激。

标签: c#wpfprismprism-7

解决方案


我尝试了一下,并提出了以下建议:

应用程序:

public partial class App : PrismApplication
{ 
    protected override Window CreateShell()
    {
        return Container.Resolve<Login>();
    }
    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.Register(typeof(object), typeof(Login), "Login");
        containerRegistry.RegisterInstance(typeof(LoginViewModel), new LoginViewModel(Container.GetContainer(), Container.Resolve<RegionManager>()));
        containerRegistry.Register(typeof(object), typeof(MainWindow), "MainWindow");
        containerRegistry.RegisterInstance(typeof(MainWindowViewModel), new MainWindowViewModel(Container.GetContainer(), Container.Resolve<RegionManager>()));
    }
}

XAML:

<Window x:Class="LoginTest.Views.Login"
    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:LoginTest.Views"
    xmlns:prism="http://prismlibrary.com/"
    prism:ViewModelLocator.AutoWireViewModel="True"
    mc:Ignorable="d"
    Title="Login" Height="250" Width="400">
<Grid>
    <Button Content="Login" HorizontalAlignment="Left" Height="61" Margin="100,100,0,0" VerticalAlignment="Top" Width="164" Command="{Binding LoginCommand}"/>

</Grid>

代码隐藏:

public partial class Login : Window
{
    public Login()
    {
        InitializeComponent();
        ((LoginViewModel)DataContext).NewWindow += StartMainApp;
        ((LoginViewModel)DataContext).CloseWindow += CloseWindow;
    }

    private void StartMainApp(Object win)
    {
        Application.Current.MainWindow = (Window)win;
        Application.Current.MainWindow.Show();
    }

    private void CloseWindow()
    {
        this.Close();
    }
}

视图模型:

class LoginViewModel : BindableBase
{
    private readonly IUnityContainer _container;
    private readonly IRegionManager _regionManager;
    private PrismApplication _application;


    private string _title = "Prism Application";
    public string Title
    {
        get { return _title; }
        set { SetProperty(ref _title, value); }
    }

    public DelegateCommand LoginCommand { get; set; }
    public delegate void NewWindowDelegate(Object win);
    public delegate void CloseWindowDelegate();
    public CloseWindowDelegate CloseWindow{ get; set; }
    public NewWindowDelegate NewWindow { get; set; }

    public LoginViewModel(IUnityContainer container, IRegionManager regionManager)
    {
        _regionManager = regionManager;
        _container = container;

        LoginCommand = new DelegateCommand(OnLogin);
    }

    private void OnLogin()
    {
        Trace.WriteLine("Logging in");
        // do your login stuff

        // If Login OK continue here
        NewWindow.Invoke(_container.Resolve<MainWindow>());
        CloseWindow.Invoke();

    }
}

我希望我的例子有任何用处!


推荐阅读