I would like my application to open with a splash screen of a .ico or image file for a few seconds, then open to my MainWindow. Is there a way to do this yet, perhaps similar to how WPF handles splash screens? WPF and WinForms handles this by setting Build Action in an images properties to Splash Screen, but this option doesn't seem to be present in Avalonia.
My other idea is to create a separate window with the image that would, when the application is run, open for a certain amount of time before closing and opening to MainWindow. I would prefer to use a simpler method like WPF though.
I never used the build in wpf splash screen you mention. Didn't know that exists. I usually show a dedicated window that I can send messages to from several threads to display current status etc. When loading is finished I close the splash and show the main window.
That's probably the cleanest and most reusable way.
I thought that may end up being the solution I'd have to use. How would you change it from opening to the MainWindow to the new dedicated window for the splash? I just need it to open the splash window and then close after a few seconds and open MainWindow, what would be the best way of accomplishing this?
Just start the app without an MainWindow AppBuilder.Start(). You should be able to override Application.OnStartup. First create your Splash and show it. Then do whatever you need to load etc before showing the MainWindow. When loading is finished close your Splash and show your MainWindow. Don't forget to assign your MainWindow to Application.MainWindow
This is only working with recent nightly build and will probably change before Avalonia hits 1.0
Just for information, UWP shows splash screen in main window until Window.Current.Activate(); is not called and main page is ready. It could be useful for Android and iOS applications. For desktop it seems just as an alternative for splash screen in separate window.
But it still can be implemented manually and is not blocked by Avalonia.
I think this will be handy on mobil plattforms
Mobile has no concept of a window
On mobile platforms splash screens should be shown before initializing Avalonia, since that is one of the expensive parts of UI initialization. On desktop you can just create a window without decorations, something like this:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyApp.SplashWindow"
Title="Loading MyApp" Width="300" Height="300"
WindowStartupLocation="CenterScreen" HasSystemDecorations="False" CanResize="False">
<TextBlock TextAlignment="Center" Text="{Binding StartupProgressText}"/>
</Window>
I created a splash window as you have @kekekeks. In the Program.cs file, under the AppMain method I have put in the code:
Splash Splash = new Splash();
Splash.Show();
Thread.Sleep(3000);
Splash.Close();
app.Run(new MainWindow());
But this just waits 3 seconds and opens only my Main Window. If I remove the Splash.Close(); it waits 3 seconds then opens both my Splash window and Main Window. Should this be a valid way of opening the splash window? The other option I considered was the use of timers.
Window needs a running main loop to function properly. You can use a custom cancellation token for app.Run and do the rest of initialization like this:
private static void AppMain(Application app, string[] args)
{
var stop = new CancellationTokenSource();
async void Start()
{
await Task.Delay(10);
var splashViewModel = new SplashViewModel();
var splash = new SplashWindow {DataContext = splashViewModel};
splash.Show();
app.MainWindow = await GetMainWindowAsync(splashViewModel);
app.MainWindow.Closed += (_, __) => stop.Cancel();
app.MainWindow.Show();
app.MainWindow.Activate();
splash.Close();
}
Start();
app.Run(stop.Token);
}
static async Task<MainWindow> GetMainWindowAsync(SplashViewModel splashViewModel)
{
// Initialize here
return new MainWindow();
}
Overriding OnStartup should be easier. This scenario is one reason why I implemented it.
It will be easier, no doubt, but will not work for the same reason that @colinparks's code doesn't: you can not have synchronous initialization.
@Gillibald if you have new ideas regarding the lifetime, please, write them down in https://github.com/AvaloniaUI/Avalonia/issues/2564 tracking issue to keep everything in one place
@kekekeks The code worked perfectly. I created a ViewModel for my SplashWindow because I didn't have one before (my SplashWindow is just an image with no data bindings) and added a await Task.Delay(3000) in the // Initialize here to show the SplashWindow for 3 seconds. Thank you for your help everyone.
Most helpful comment
Just for information, UWP shows splash screen in main window until Window.Current.Activate(); is not called and main page is ready. It could be useful for Android and iOS applications. For desktop it seems just as an alternative for splash screen in separate window.
But it still can be implemented manually and is not blocked by Avalonia.