WPF PRISM 7登录窗口在主窗口之前

时间:2019-06-03 20:50:24

标签: c# wpf prism prism-7

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

我在这里查看了几个答案,但是所有答案都使用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,但是我可以弄清楚如何从Main app订阅该事件

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

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

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

应用程序:

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();
    }
}

ViewModel:

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();

    }
}

我希望我的例子有用!

答案 1 :(得分:0)

我要感谢user947737的良好建议。我自己尝试过,对我来说很有效。 另外,当然,我添加了MainWindowsMo​​delView构造函数。

public class MainWindowViewModel : 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 MainWindowViewModel(IUnityContainer container, IRegionManager regionManager)
        {
            _container = container;
            _regionManager = regionManager;
        }
    }