We are working on an application with a splash screen. After a few seconds/loading all the data, a login dialog appears inside the splash screen, asking you to enter username and password. Think of a Visual Studio splash screen when you run it for the first time.
Here is how I have done it:
SplashScreenView.xaml.cs:
public partial class SplashScreenView : MetroWindow
{
public SplashScreenView()
{
InitializeComponent();
}
async private void MetroWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
this.Closing -= MetroWindow_Closing;
bool dialogResult = true;
LoginDialogData loginDialogData;
do
{
loginDialogData = await this.ShowLoginAsync
(
"Log In",
"Please log in!",
new LoginDialogSettings
{
ColorScheme=MetroDialogColorScheme.Accented,
UsernameWatermark = "Username...",
PasswordWatermark = "Password...",
NegativeButtonVisibility=Visibility.Visible
}
);
if(loginDialogData == null)
{
dialogResult = false;
break;
}
}
while (!(await AttemptLogin(loginDialogData.Username,loginDialogData.Password)));
CloseWindow(dialogResult);
}
private Task<bool> AttemptLogin(string userName,string password)
{
SplashScreenViewModel viewModel = (SplashScreenViewModel)this.DataContext;
return Task.Run<bool>(() => viewModel.Login(userName, password));
}
private void CloseWindow(bool dialogResult)
{
Storyboard sb = this.FindResource("WindowClosingStoryboard") as Storyboard;
sb.Completed += (s,e) => ((SplashScreenViewModel)this.DataContext).TryClose(dialogResult);
sb.Begin();
}
}
SplashScreenViewModel.cs:
public class SplashScreenViewModel : Screen
{
ISchoolTestMakerServiceProxy serviceProxy;
private string currentStatus;
public SplashScreenViewModel(ISchoolTestMakerServiceProxy serviceProxy)
{
this.serviceProxy = serviceProxy;
}
public bool Login(string userName,string password)
{
userName = "Pesho Daskala";
password = "parola123"; //don't worry it's fake :D
return serviceProxy.Connect(userName, password);
}
}
AppBootstrapper.cs(The relevant part):
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
{
Application.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
var windowManager = container.Resolve<IWindowManager>();
if (ShowSplashScreen())
{
Application.ShutdownMode = System.Windows.ShutdownMode.OnMainWindowClose;
this.DisplayRootViewFor<IShell>();
}
else
{
Application.Shutdown();
}
}
private void InitializeApplication()
{
Thread.Sleep(1000);
}
private bool ShowSplashScreen()
{
var splashScreenViewModel = container.Resolve<SplashScreenViewModel>();
var windowManager = container.Resolve<IWindowManager>();
Task.Run(() => InitializeApplication())
.ContinueWith((r) =>
{
splashScreenViewModel.TryClose();
});
return windowManager.ShowDialog(splashScreenViewModel)==true;
}
Before you kill me for using code behind, I want to say that in my opinion displaying the login dialog is view related work and the viewmodel shouldn't know anything about it. All that the viewmodel needs to do is get the credentials from the view, submit them to the server and give the response back to the view, which is then responsible for showing a closing animation and all that good stuff before actually closing.