Как обрабатывать вход / выход в Caliburn.Микро?

Я новичок в Калибурн.Micro, и мне интересно, каков наилучший способ обработки циклов входа/выхода пользователя в моем приложении. Я видел некоторые предложения в интернете, чтобы реализовать это с помощью пустой оболочки, которая переключается между LoginView и основным представлением приложения, каждый с пользовательской ViewModel, конечно.

Мне не очень нравится это решение, потому что для меня это 2 отдельных окна с очень разными свойствами (название, значок, размер) и кажется нечистым решение двух измените одно окно на другое. Другая проблема заключается в том, что окно входа в систему происходит из служебной библиотеки, которую я не контролирую и которая не использует Caliburn.Микро, это простое старое окно, которое дает мне событие, когда пользователь нажимает "войти".

Я также видел предложения по отображению этого диалога в методе запуска Bootstrapper, но проблема, которую я вижу, заключается в том, что пользователь может выбрать "выход" из приложения, которое должно снова отобразить диалоговое окно входа. Кажется неправильно для меня обрабатывать переключение между представлениями в загрузчике.

Я хотел бы иметь какой-то ApplicationViewModel или ApplicationController, который работает как проводник Caliburn, но вместо переключения между представлениями внутри окна он должен переключаться между LoginWindow и MainWindow, а также должен обрабатывать закрытие всего приложения (что также требует выхода из системы). При активации он покажет LoginWindow, обработает событие входа в систему и затем переключитесь в Главное окно (Shell). Если пользователь выбирает "выход", событие должно снова всплывать до ApplicationViewModel / Controller, который деактивирует / закроет MainWindow, выполнит выход, а затем снова покажет LoginDialog. Аналогичное событие Close выполнит выход из системы, но затем завершит работу всего приложения.

Итак, мои вопросы:

  1. что вы думаете об этом решении и у тебя есть другой/лучше?
  2. как я реализовать это? ;-)

Спасибо большое!

2 ответов


я думаю, что решение вашей проблемы довольно легко.

в двух словах вы создаете одну ViewModel как оболочку, которая представлена с окном входа в систему при запуске приложения. Если пользователь успешно входит в систему, это окно закрывается и тот же экземпляр viewModel отображается в окне содержимого. Если пользователь выполняет выход из системы, окно входа отображается снова.

прежде всего создайте интерфейс IShell, который предоставляет два делегата LoginSuccessful и Logout

public interface IShell
    {
        Action LoginSuccessful { get; set; }
        Action Logout { get; set; }
    }

далее создайте класс ShellViewModel, который реализует IShell

 public class ShellViewModel : Screen, IShell
    {
        public ShellViewModel()
        {
            LoginSuccessful = delegate { };
            Logout = delegate { };
        }

        public Action LoginSuccessful { get; set; }
        public Action Logout { get; set; }

        public void DoLogin()
        {
            LoginSuccessful();
        }

        public void DoLogout()
        {
            Logout();
        }
    }

методы DoLogin и DoLogout являются действия, которые могут быть связаны с Button или любой контроль, подходящий для вас.

следующий шаг-переопределить OnStartupMethod в свой загрузчик. Это предпосылки, что у вас есть экземпляр WindowManager и ShellViewModel экспортируется IOC Framework по вашему выбору.

protected override void OnStartup(object sender, StartupEventArgs e)
        {
            var windowManager = IoC.Get<IWindowManager>();
            var viewModel = IoC.Get<IShell>();

            viewModel.LoginSuccessful =
                () => GuardCloseAndReopen("Content");

            viewModel.Logout =
                () => GuardCloseAndReopen("Login");

            windowManager.ShowWindow(viewModel, "Login");
        }

        private void GuardCloseAndReopen(string shellViewMode)
        {
            var windowManager = IoC.Get<IWindowManager>();
            var shellScreen = IoC.Get<IShell>() as Screen;

            Application.ShutdownMode = ShutdownMode.OnExplicitShutdown;

            shellScreen.TryClose();

            Application.ShutdownMode = ShutdownMode.OnLastWindowClose;

            windowManager.ShowWindow(shellScreen, shellViewMode);
        }

трюк в этом: если DoLogout вызывается метод, текущее окно закрывается вызовом TryClose на ShellViewModel. В то же время вы предотвратите завершение работы приложения, установив Application.ShutdownMode to OnExplicitShutdown. Затем, используя windowmanager, вы создаете другое окно в режиме входа в систему, передавая" Login " в качестве контекстной информации windowManager. На самом деле это та же ViewModel, однако с другим визуальным представлением.

на Logout вы делаете то же самое просто вокруг.

чтобы получить эту работу с использованием соглашений Caliburn, вам нужна специальная структура проекта, как показано здесь (и объяснено здесь): enter image description here

теперь я призываю вас взять этот код и создать небольшой пример приложения. Создать Login View (который входит в систему с помощью кнопки или что-то еще) и создать Content просмотр с помощью кнопки выхода из системы С помощью методов LoginSuccessful/ Logout.

это решит вашу проблему с минимумом Код и классы. Надеюсь, это вам поможет.


Я попытался создать что-то, что в основном работает, но, вероятно, нужно немного больше работы, чтобы быть действительно полезным. Полностью комментарии и источник можно найти на этом посту Калибурн.Пример окна входа в систему Micro на моем сайте.

я использовал IEventAggregator в Калибурн.Micro для управления переходом между двумя окнами. Вы получаете этот код, чтобы открыть экран входа в систему:

public void Handle(LoginEvent message)
{
    LoginWindow loginWindow = new LoginWindow();
    loginWindow.Login += new EventHandler<LoginEventArgs>(this.LoginWindow_Login);
    loginWindow.Cancel += new EventHandler(LoginWindow_Cancel);
    loginWindow.ShowDialog();
}

этот же источник используется как в первый раз, когда приложение открывается и когда событие выхода из системы опубликовано. событие Logout выглядит следующим образом:

public void Handle(LogoutEvent message)
{
    Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
    message.Source.TryClose();
    Application.Current.ShutdownMode = ShutdownMode.OnLastWindowClose;
    this.events.Publish(new LoginEvent());
}

при успешном входе в систему он использует этот код, чтобы открыть главное окно, которое основано на ViewModel:

ContentViewModel viewModel;
viewModel = IoC.Get<ContentViewModel>();
viewModel.Username = e.Username;
this.windowManager.ShowWindow(viewModel);