Splash-Fenster sind Fenster, die beim Starten einer Anwendung erscheinen, um dem Anwender
während einer länger andauernden Initialisierungsphase Informationen anzubieten oder um einfach nur anzuzeigen, dass das Programm im Moment initialisiert wird.
Ein vernünftiges Splash-Fenster ist unter WPF aber erstaunlicherweise gar nicht so einfach zu
implementieren. Ein im Startup-Ereignis der App-Instanz direkt angezeigtes Splash-Fenster kann zum Beispiel keine Informationen anzeigen, die während der Initialisierung ausgegeben werden sollen. Außerdem werden Animationen, die auf dem Splash-Fenster angelegt sind, nicht ausgeführt.
Eine Lösung dieser Probleme ist, die Initialisierung der Anwendung im Startup-Ereignis der App-Instanz asynchron auszuführen und das Splash-Fenster ebenfalls asynchron zu schließen.
Die folgende Lösung entstammt dem Buch "Das C# 2010 Codebook" und wurde vom Autor mit freundlicher Genehmigung des Verlags veröffentlicht.
/* Dieses Snippet ist eines der 418 Rezepte des Buchs "Das C# 2010 Codebook" und wurde vom Autor mit freundlicher Genehmigung des Verlags veröffentlicht. */
/* Basis dieser Lösung ist, dass Sie in der App.xaml-Datei kein Startfenster angeben.
Das Startfenster wird, neben dem Splash-Fenster, von einem asynchron aufgerufenen
Delegaten in der überschriebenen OnStartup-Methode der Anwendung geöffnet. */
/* Der XAML-Code des Beispiel-Splash-Fensters */
<Window x:Class="..."
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="180" Width="280"
WindowStyle="None">
<Grid>
<TextBlock Name="txtInfo" Margin="10,10,0,28" TextWrapping="Wrap"
HorizontalAlignment="Left" Width="166">Info</TextBlock>
<ProgressBar Name="pbr" Height="20" VerticalAlignment="Bottom"/>
</Grid>
</Window>
/* Methode in der Klasse des Splash-Fensters */
public void SetInfo(string info, int progress)
{
this.txtInfo.Text = info;
this.pbr.Value = progress;
}
/* Die App-Klasse */
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// Splash-Fenster öffnen
SplashWindow splashWindow = new SplashWindow();
splashWindow.Show();
// Delegat für die asynchrone Ausführung
// der Initialisierung
Action initializer = new Action(() =>
{
// Simulation einer Initialisierung
try
{
/* Initialisierung */
for (int i = 0; i < 100; i++)
{
// Das Splash-Fenster aktualisieren
splashWindow.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(() =>
{
splashWindow.SetInfo("Lese Datensatz " + i + " ...", i);
}));
// Die eigentliche Initialisierung wird hier nur simuliert
System.Threading.Thread.Sleep(30);
}
/* Ende der Initialisierung */
}
catch (Exception ex)
{
MessageBox.Show("Fehler beim Initialisieren: " + ex.Message,
"Splash-Fenster", MessageBoxButton.OK, MessageBoxImage.Error);
this.Shutdown();
}
});
// Delegat für den Callback der asynchronen Ausführung
AsyncCallback splashCloser = new AsyncCallback((result) =>
{
// Das Hauptfenster erzeugen, der Anwendung zuweisen
// und öffnen
this.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(() =>
{
MainWindow mainWindow = new MainWindow();
this.MainWindow = mainWindow;
mainWindow.Show();
}));
// Schließen des Splash-Fensters
splashWindow.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(() =>
{
splashWindow.Close();
}));
});
// Asynchrones Starten der Initialisierung
initializer.BeginInvoke(splashCloser, null);
}
}
1 Kommentare zum Snippet