How to handle input / output in Caliburn.Micro?

I'm new to Caliburn.Micro, and I am wondering what is the best way to handle user login / logout cycles in my application. I saw several suggestions on the Internet to implement this using an empty Shell-View that switches between LoginView and the main application view, each of which has a custom ViewModel, of course.

I don’t like this solution, because for me it is two separate windows with very different properties (Title, Icon, Size), and it seems that this is an unclean solution that changes one window to look like another. Another problem is that the login window comes from a utility library that I do not control and that does not use Caliburn.Micro, this is a simple old window that gives me an event when the user clicks "Login".

I also saw suggestions for displaying this dialog in the Bootstrapper startup method, but the problem I see in this is that the user can select the "Exit" application, which should again display the "Login" dialog box. It seems to me wrong to handle switching between views in Bootstrapper.

I would like to have some kind of ApplicationViewModel or ApplicationController that works like Caliburn Explorer, but instead of switching between views inside the window, it should switch between LoginWindow and MainWindow and should also handle Closing the whole application (which also requires logging out). In the "Activation" section, he will show LoginWindow, process the "Login" event, and then switch to the main window ("shell"). If the user selects "LogOut", the event should again appear in the ApplicationViewModel / Controller, which deactivates / closes MainWindow, logs off, and displays LoginDialog again. A similar Close event throws Logout, but then shuts down the entire application.

So my questions are:

  • What do you think of this decision and you have another / best?
  • How to implement this ?; -)

Thanks a lot!

+6
source share
2 answers

I think the solution to your problem is quite simple.

In a nutshell, you create one ViewModel as a shell that appears when you log in when the application starts. If the user logs in successfully, this window closes, and the same instance of viewModel is displayed in the content window. If the user logs out, the login window is displayed again.

First of all, create an IShell interface that provides two delegates LoginSuccessful and Logout

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

Then create a ShellViewModel class that implements 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(); } } 

The DoLogin and DoLogout methods are actions that can be bound to a Button or any other control suitable for you.

The next step is to override OnStartupMethod in your Bootstrapper. In this case, you have an instance of WindowManager and ShellViewModel exported by the IoC Framework of your choice.

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

The trick for this: if the DoLogout method is DoLogout , the current window closes by calling TryClose on the ShellViewModel . At the same time, you cannot disable the application by setting Application.ShutdownMode to OnExplicitShutdown . Then, using windowmanager, you create another window in login mode, passing "Login" as the context information to windowManager. This is, in fact, the same ViewModel, but with a different visual representation.

For Logout you do the same only around.

To get this working using Caliburn conventions, you need a special project structure, as shown here (and explained there ): enter image description here

Now I urge you to take this code and create a small sample application. Create a Login View (which logs in with a button or something else) and create a Content View with a Logout button using the LoginSuccessful / Logout methods.

This will solve your problem with a minimum of code and classes. Hope this will be helpful for you.

+16
source

I have an idea to create something that basically works, but it will probably take a little more work to be really useful. Full comments and sources can be found on this post Caliburn.Micro Login Window image on my website.

I used IEventAggregator Caliburn.Micro to control the transition between two windows. You will receive this code to open the login screen:

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

the same source is used both at the first opening of the application and when publishing the event log. the Exit event is as follows:

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

When the login is successful, it uses this code to open the main window based on the ViewModel:

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

Source: https://habr.com/ru/post/922912/