WPF Grundlagen – Wie finden Applikation und Fenster zusammen?
Die Projektvorlagen dieser Welt machen es dem Entwickler heutzutage sehr einfach, zu einer lauffähigen Anwendung zu kommen. Ein paar Klicks und schon ist das Gerüst z.B. für eine WPF Applikation fertig. Dabei passiert aber auch so manches hinter den Kulissen, was auf den ersten Blick nicht so leicht ersichtlich ist. Deswegen stellen wir uns heute die Frage, wie bei einer vom Visual Studio generierten WPF Anwendung, das Applikationsobjekt und das Hauptfenster zusammenfinden.
Wie sieht die Struktur einer WPF Anwendung aus, die mit dem Projekttemplate von Visual Studio 2008 erstellt wurde?
Der Screenshot zeigt den Aufbau einer solchen WPF Applikation. Es fallen auf Anhieb zwei Teile auf, die jeweils aus einem XAML File und einem C# File bestehen:
- App.* – beschreiben das Applikationsobjekt
- Window1.* – beschreiben das Hauptfenster der Applikation
- Und, wie nicht anders zu erwarten, läuft das Programm wenn F5 im Studio gedrückt wird. Aber was passiert hier? Dazu werfen wir einen Blick auf den Sourcecode.
XAML File für das Haupfenster
<Window x:Class="WpfApplication.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
</Grid>
</Window>
Hier gibt es nichts spektakuläres zu sehen. Es wird ein Objekt vom Typ Window definiert, ein paar Eigenschaften wie Titel, Höhe und Breite angegeben und zwei XML Namespaces eingebunden. Interessant ist der Teil “x:Class=”WpfApplication.Window1”. Mit dem Attribut x:Class wird angegeben, dass zu diesem XAML Code noch ein weiterer Teil, nämlich der C# Teil gehört. “WpfApplication” gibt hierbei den Namespace und “Window1” den Klassennamen an. Ein Blick in das zugehörige C# File zeigt dann auch eine partielle Klasse Window1.
C# File für das Hauptfenster
using System.Windows;
namespace WpfApplication
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}
Bei einem frisch erstellten Projekt ist diese Code-Behind Datei bis auf den Aufruf von “InitializeComponent()” ziemlich leer (die überflüssigen “using” Anweisungen habe ich gleich vom Resharper entfernen lassen).
XAML File für die Applikation
<Application x:Class="WpfApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
</Application.Resources>
</Application>
Der Aufbau ist ähnlich wie bei dem Window. Hier taucht erstmals eine Verbindung zwischen der Applikation und dem Fenster auf, indem das StartupUri Attribut auf den Dateinamen des XAML Files des Fensters gesetzt wird.
C# File für die Applikation
using System.Windows;
namespace WpfApplication
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}
Hier herrscht gähnende Leere. Die partielle Klasse des Applikationsobjektes ist komplett leer. Jetzt stellt sich die Frage, wo denn die “Main” Methode unserer Applikation ist. Irgendwie muss die Anwendung ja gestartet werden. Hier hilft uns der “Show All Files” Button im Solution Explorer weiter:
Jetzt werden auch alle temporären Dateien angezeigt, die während des Kompiliervorgangs entstanden sind. Aus dieser Vielzahl sehen wir uns ein File ein bisschen genauer an:
App.g.cs
Das ‘g’ im Dateinamen steht für “generated”. Es handelt sich hier also um einen generierten Teil der Applikationsklasse. Ich picke mal den interessanten Teil heraus:
...
public void InitializeComponent() {
#line 4 "..\..\App.xaml"
this.StartupUri = new System.Uri("Window1.xaml", System.UriKind.Relative);
#line default
#line hidden
}
/// <summary>
/// Application Entry Point.
/// </summary>
[System.STAThreadAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static void Main() {
WpfApplication.App app = new WpfApplication.App();
app.InitializeComponent();
app.Run();
}
...
Et voilà, hier findet sich auch eine Main() Methode welche den Einstiegspunkt für das Programm darstellt. In InitializeComponent() findet sich auch wieder die StartupUri Eigenschaft, die in App.xaml gesetzt wurde. Durch das setzen dieser Eigenschaft wird das von der URI referenzierte Fenster beim Start der Applikation angezeigt und als dessen Hauptfenster gesetzt (ist also über Application.Current.MainWindow erreichbar).
Auch wenn es den erfahrenen WPF Entwickler vielleicht gelangweilt haben mag – ich finde solche Grundlagen wichtig. Eventuell war ja für den einen oder anderen WPF Einsteiger etwas Neues/Interessantes dabei.






