WPF PRISM 7 Окно входа в систему перед главным окном - PullRequest
0 голосов
/ 03 июня 2019

Я новичок в WPF / Prism и пытаюсь сделать следующее: мне нужно загрузить окно входа в систему (окна или пользовательский элемент управления) перед запуском моего главного окна. После успешного входа в систему удалите представление «Вход в систему» ​​и перейдите в главное окно.

Я рассмотрел несколько ответов здесь, но все они ссылаются на более старые версии PRISM с классом Boostrapper.

У меня есть приложение 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 вручную вместо того, чтобы делать это за вас, выглядит немного странно.

Кроме того, InitiallizeShell в PRISM 7 ожидает создания текущей оболочки. Я не уверен, следует ли мне использовать это значение, передаваемое для активации главного окна.

 protected override void InitializeShell(Window shell)

Я также читал от самого Брайана Лагунаса на Github, чтобы, возможно, использовать EventAggregator (который я пробовал). У меня был модуль авторизации, который регистрирует EventAggregator и из LoginViewModel, при успешном входе в систему, публикует SuccessfulLoginEvent, но я могу выяснить, как подписаться на это событие из основного приложения

Таким образом, в основном ожидаемый результат состоит в том, что когда приложение запускается, если пользователь не вошел в систему, показать LoginView, после того как пользователь сам себя аутентифицирует, перевести его в MainWindow со всеми уже загруженными необходимыми модулями.

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 18 июля 2019

Я попробовал и придумал следующее:

App:

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>

Codebehind:

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

    }
}

Надеюсь, мой пример пригодится!

...