Zurück zur Übersicht

XAML

Daniel Wolf

Einleitung

XAML ist eine von Microsoft entwickelte Auszeichnungssprache zur strukturierten Beschreibung von Benutzeroberflächen. Das Akronym steht inzwischen für "extensible application markup language"; davor stand das A für Avalon, den ursprünglichen Codenamen des neuen Grafiksystems von Windows Vista. Korrekt wird XAML wie das bayerische Wort für Brötchen ausgesprochen.

Die Vision

Mit Windows Vista (vormals Longhorn), der Windows Presentation Foundation (vormals Avalon) und .NET 2.0 strebt Microsoft eine neue, flexiblere Softwarearchitektur an. Insbesondere die bisherige Trennung zwischen Webapplikationen und Anwendungssoftware soll verschwimmen. Erstere erlauben insbesondere einfache Verwendung (ohne Installation), unmittelbare Updates (durch simples Überschreiben der online befindlichen Dateien) und flexible Darstellung auf verschiedensten Ausgabegeräten (dank Trennung von Inhalt und Formatierung durch HTML/CSS). Letztere bieten dafür mehr Möglichkeiten zur Erstellung von Benutzeroberflächen mithilfe einer großen Auswahl an Standard-GUI-Elementen; außerdem lassen sie sich installieren und damit auch offline ausführen.
Microsofts Vision verbindet das Beste beider Welten. .NET-Applikationen sollen ohne Code-Änderungen direkt online ausführbar sein, sich aber auch wie klassische Windows-Anwendungen auf einem Rechner installieren lassen. Durch die Ausführung von binärem Zwischencode können auch lokal installierte Anwendungen in einer "Sandbox" laufen, ohne auf kritische Systembereiche zugreifen zu können (so zumindest die Theorie). Dank automatisch integrierter "Nach-Hause-telefonieren"-Option überprüfen diese Anwendungen selbstständig, ob Updates vorliegen, und installieren diese gegebenenfalls automatisch. Sie haben Zugriff auf sämtliche Win32-GUI-Elemente sowie auf das gesamte Windows-API (inklusive DirectX für Hardware-beschleunigte Multimediaanwendungen), bieten aber zugleich eine Flexibilität in der Darstellung, wie man sie sonst von HTML-basierten Internetanwendungen kennt: Mit Windows Vista will Microsoft sich ganz von der Pixel-basierten Designlogik trennen und auf Fenster mit frei skalierbaren Inhalten setzen, die sich je nach Anforderung dynamisch umarrangieren.

Die Umsetzung

Grafische Windows-Programmierung hat im Laufe der Zeit mehrere Abstraktionsstufen durchlaufen. Die klassische Art, Fenster und andere GUI-Elemente zu erzeugen, ist durch direkten Aufruf der API-Funktionen, d.h. durch reinen imperativen Programmcode. Das folgende C++-Codefragment zeigt das Hinzufügen einer einfachen Schaltfläche in ein Fenster:

HWND hwndButton = CreateWindow(
	TEXT("button"),
	TEXT("Click me!"),
	WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
	0, 0, 200, 200,
	hwnd, (HMENU)0,
	hInstance, NULL);

Dieses direkte Verwalten von Window-Handles auf unterster Ebene erzeugt umständlichen, aufgeblähten, schlecht zu lesenden Code, der zudem die Umsetzung des GUI-Designs mit dem funktionalen Quellcode verschmilzt und dadurch eine (wünschenswerte) Trennung von Oberfläche und Funktionalität wirksam verhindert, von einer Trennung zwischen logischem GUI-Aufbau und tatsächlicher Darstellung ganz zu schweigen: Die Pixel-Positionen der grafischen Elemente sind in den Quelltext eingegossen.

Um die Erzeugung von Programmoberflächen zu vereinfachen, führte Microsoft 1992 die Microsoft Foundation Classes (MFC) ein, eine Sammlung objektorientierter Klassenbibliotheken, die als Wrapper um die eigentlichen API-Aufrufe dienten. In ähnlicher Weise bietet z.B. auch Java eine objektorientierte Repräsentation von GUI-Objekten. Hier ein zum obigen Quelltext quasi gleichwertiges C#-Fragment:

button = new MSAvalon.Windows.Controls.Button();
button.Text = "Click me!";
mainWindow.Children.Add(button);

Die objektorientierte Version bietet den Vorteil einer Zusätzlichen Abstraktionsebene, die dem Programmierer das umständliche und fehlerträchtige Hantieren mit Handles abnimmt. Statt eines elf-argumentigen Funktionsaufrufs müssen nur die Eigenschaften explizit angegeben werden, die von den Default-Werten abweichen. Durch die Verwendung der neuen Funktionen der Windows Presentation Foundation ist es so sogar möglich, Elemente grafischer Oberflächen ausschließlich logisch zu positionieren, sodass die tatsächliche Darstellung (Größe, Position) zur Laufzeit auf der Grundlage von Anzeigemedium, Darstellungsfläche und Benutzerpräferenzen optimal gewählt werden kann - wie bei HTML-Code.
XAML geht nun noch einen Schritt weiter. Es trennt die logische Oberflächenstruktur nicht nur von der tatsächlichen Darstellung, es gliedert sie auch komplett aus dem Quelltext aus. XAML erlaubt es, den logischen Aufbau einer GUI in Form eines XML-Dokuments zu beschreiben. Aus diesem Dokument werden automatisch Objektdeklarationen generiert: Tags werden zu Klasseninstanzen, Attribute zu Eigenschaften. Das folgende Beispiel soll dies verdeutlichen:

<Window xmlns="http://schemas.microsoft.com/2003/xaml" Visible="true">
    <Button>Click me!</Button>
</Window>

Hierbei erzeugen die erste und letzte Zeile automatisch ein Objekt von Typ Window; die zweite Zeile fügt den Button ein. Somit ersetzt ein einziges XAML-Element drei Zeilen objektorientierten Code oder einen Funktionsaufruf mit elf Parametern.
In dieser Weise kann man die gesamte Beschreibung einer grafischen Benutzeroberfläche in ein kompaktes XAML-Dokument ausgliedern. Zur Compilezeit werden daraus automatisch wieder Objekte generiert, auf die man im Programmcode ebenso zugreifen kann, als seien sie manuell wie im zweiten Code-Beispiel deklariert worden.

Über die Deklaration von Objekten hinaus erlaubt XAML auch das direkte Einfügen von Quellcode, um beispielsweise auf Benutzerereignisse direkt reagieren zu können. Da dies jedoch dem Ideal der Trennung von Oberfläche und Programmierung zuwiderläuft, sollte von dieser Möglichkeit nur sehr sparsam Gebrauch gemacht werden. Ich werde auf diese Option daher nicht weiter eingehen.

Im Folgenden noch ein Ausschnitt aus einer etwas komplexeren GUI-Definition in XAML (von http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnintlong/html/longhornch03.asp).

<Border Background="white"
    xmlns="http://schemas.microsoft.com/2003/xaml"
    xmlns:def="Definition">
  <FlowPanel>
    <FlowPanel.Resources>
      <Style def:Name="RoundButton">
    
         <Button FontSize="20"/>
     
         <Style.VisualTree>
             <Canvas>
                 <Rectangle ID="MainRect" 
                     RadiusX="10" RadiusY="10" 
                     Fill="*Alias(Target=Background)" 
                     Width="100%" Height="100%" />

                 <FlowPanel Width="100%" Height="100%" >
                     <ContentPresenter  
                          ContentControl.Content="*Alias(Target = Content)" 
                          Margin="15,3,15,5"/>
                 </FlowPanel>
             </Canvas>
         </Style.VisualTree>
      </Style>
    </FlowPanel.Resources>
 
    <Button Style="{RoundButton}">
        standard RoundButton
    </Button>

    <Button Background="red" Style="{RoundButton}">
        red RoundButton
    </Button>

    <Button>
        standard button
    </Button>

    <Button Background="red">
        red standard button
    </Button>
  </FlowPanel>
</Border>

Interessant ist hier - außer der Tatsache, dass die gesamte Objekthierarchie komplett in XML dargestellt ist - vor allem die Verwendung eines FlowPanel-Objekts. Hierdurch kann für das Oberflächendesign auf absolute Pixelangaben weitestgehend verzichtet werden. Unter Windows Vista kann daher die Darstellung - wie bei einem HTML-Dokument - nach Belieben vergrößert und verkleinert werden.
Bemerkenswert ist außerdem die Tatsache, dass die tatsächliche Darstellung des FlowPanel-Objekts von der Breite der Darstellung abhängig ist: passen die einzelnen Objekte nicht nebeneinander auf die Darstellungsfläche, so werden sie dynamisch umgebrochen - ebenfalls wieder wie bei HTML-Dokumenten. Auf diese Art lassen sich mit XAML und der Windows Presentation Foundation auf elegante Art und Weise Anwendungen erzeugen, die ihre Darstellung flexibel der jeweiligen Ausgabesituation anpassen, ohne dabei die aus der klassischen Windows-Programmierung gewohnten Möglichkeiten einzuschränken.