Inhaltsverzeichnis         

WPF Einführung

WPF- Windows Presentation Foundation

Mit dem Betriebssystem Windows Vista wurde die .NET Bibliothek WPF eingeführt. Es ist der Versuch, die Implementierung nativer Windows- Clients in technischer als auch organisatorischer Sicht auf eine modernere Grundlage zu stellen. Es werden folgende Ziele angestrebt:

  1. Einsatz der umfangreichen Hardwarebeschleunigung durch moderne Grafikkarten in der Implementierung

  2. einfache Implementierung von Farbverläufen, Animationen und gedrehten/verzerrten Steuerelementen in der GUI

  3. bessere Ausnutzung der Bildschirmfläche durch Layouts, die sich an die Fenstergröße anpassen

  4. einfache Generierung von druckbaren Dokumenten

  5. Implementierung von 3D Objekten in der GUI

  6. Oberflächenentwurf unabhängig von den Werkzeugen des Programmierers machen

  7. Zugriff auf die GUI über das Internet (Option: Ausführen im Webbrowser)

Windows Forms und WPF – eine Gegenüberstellung

Das folgende Schichtenmodell zeigt die Unterschiede bei der Implementierung einer Windows- Form und einer WPF- Anwendung.




DirectX, milcore etc.

Durch Zugriff auf die Grafikhardware über DirectX in WPF können die Ressourcen moderner Grafikkarten voll ausgenutzt werden, um auch anspruchsvollere grafische Operationen wie Farbverläufe, gedrehte Schriften und 3D- Objekte in modernen Geschäftsanwendungen zu anzubieten.

Ein Teil der WPF- Implementierung ist unterhalb der CLR implementiert und damit unverwaltet. Hier sind Operationen ausgelagert, die eng mit DirectX verzahnt sind und äußerst ressourcenintensiv sind.

Die Mehrzahl der WPF- Klassen ist jedoch oberhalb der CLR, und damit verwaltet implementiert.

Durch diese Aufteilung des WPF- Codes in verwalteten und unverwalteten Code soll die Entwicklungs- und Portierungsarbeiten minimiert, und die Effizienz bei der Ausführung maximiert werden.

Aufteilung der Entwicklungsarbeit durch XAML

In einer WPF- Anwendung kann das Design der GUI komplett in einer XAML- XML- Datei beschrieben werden. XAML stellt damit eine XML- Schnittstelle zwischen der Welt der .NET Programmierer und der Welt der Grafiker und Designer mit ihren Lieblingstools wie Dreamwaver © etc. dar. So könnte ein Desinger die GUI mit seinem Tool in HTML entwerfen. Anschließend könnte diser Entwurf durch eine entsprechende Stylesheet- Datei in eine XAML- Beschreibung umgewandelt werden. Damit ergibt sich rein theoretisch eine strikte Trennung zwischen Oberflächenentwurf und Implementierung der Anwendungslogik.

Klassenhierarchie und Basisklassen

Durch Basisklassen werden in der WPF Prinzipien wie STA, Vererbung von Eigenschaftswerten, Flexible Layouts , Steuerelemente mit allgemeinen Inhalten und deklarative Programmierung eingeführt.

Hier ein Ausschnitt aus der Klassenhierarchie von WPF:






STA und System.Threading.DispatcherObject

STA steht für Single Thread Apartment. Jedem STA ist ein Thread zugeordnet. Nur dieser darf auf die Objekt innerhalb eines STA zugreifen. Aus anderen Threads gelingt der Zugriff nur mittels Marshalling (implementiert z.B. durch eine MessageQueue).

Daraus folgt, das STA- Anwendungen nicht reentrant sein müssen. Klassische Windows- Forms- Anwendungen, die die Nachrichtenwarteschlange auslesen und in Fensterfunktionen verarbeiten sind typische Vertreter für STA. Im folgenden nochmals ein Vergleich zwischen MTA und STA:

MTA- Multi Thread Apartment








STA – Single Thread Apartment






DispatcherObject

Aus Gründen der Kompatibilität mit der GDI und dem Windows- Betriebssystem laufen WPF- Applikationen in STA. Die DispatcherObject- Klasse ist dafür die Grundlage. Sie bietet z.B. Methoden wie CheckAccess an, mit denen die Gültigkeit des Methodenaufrufes eines WPF- Objektes aus dem aktuellen Thread heraus geprüft werden kann.

Delegieren des Setzens von WPF- Eigenschaften an den UI- Thread

Ein Anwendung findet das Dispatcher- Objekt in Situationen, wo eine WPF- Eigenschaft aus einem nicht- UI- Thread heraus gesetzt werden muss, beispielsweise einem System.Timers.Timer- Thread. Hier kann mit der Mehtode Invoke der Aufruf an den UI- Thrad delegiert werden.

System.Timers.Timer clock = new System.Timers.Timer(1000.0);

public Window1()
{
  InitializeComponent();

  // Timer einrichten
  clock.AutoReset = true;
  clock.Elapsed += new System.Timers.ElapsedEventHandler(clock_Elapsed);
  clock.Enabled = true;
}        

// Eventhandler, der im Timer- Thread aufgerufen wird, und nicht im UI- Thread!
void clock_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
  // Das Setzen der Label- Eigenschaft wird an den UI Thread delegiert.
  // Dieses Vorgehen wird durch das STA erzwungen
  Dispatcher.Invoke(
    new Action<string>(time => lblStatusTime.Content = time),
    new object[] {DateTime.Now.ToLongTimeString()});            
}        

Eigenschaftsvererbung, Trigger als DependencyProperties durch DependencyObject implementieren

In der WPF wird der imperative Programmierstil (Folge von DrawLine(...) etc. Funktionsaufrufen) durch einen deklarativen, DOM- geprägten Stil verdrängt (Aufbau eines WPF- Objektbaumes new Line(..) etc.). Die Parametrierung der der WPF- Instanzen tritt in den Vordergrund.

<Menu Name="menu1" 
      VerticalAlignment="Top" 
      Grid.Row="0" 
      FontFamily="Times New Roman" FontSize="16pt" >    ----+
 <MenuItem Name="mnuItemFile" Header="_Datei">            <-+  erben
    <MenuItem Name="mnuFileOpen"                            |
              Header="Ö_ffnen"                              |
              FontStyle="Italic"                            |  Überschreiben mit
              Click="MenuItemFileOpen_Click"/>              |  lokaler Eigenschaft
 </MenuItem>                                                |
 <MenuItem Name="mnuItemEffects" Header="_Effekte">       <-+  erben
    <MenuItem Name="mnuItemEffektGlow"                    <-+  erben
              Header="Bring es zum Glühen" 
              Click="mnuItemEffektGlow_Click"/>
 </MenuItem>
</Menu>



In WPF- Objektbäumen ist das vererben von Eigenschaftswerten an die Kind- Elemente sinnvoll. Hat ein Wurzelelement die Eigenschaft FontSize, so können die Kindelemente diese übernehmen, wodurch der Umfang bei der Definition der Objektbäume gemindert wird. Da WPF- Anwendungen "leben", indem sie z.B. auf Benutzereingaben reagieren, muss auch auf eine sich ändernden FontSize eines Elternelementes in den Kind- Elementen reagiert werden.

Eigenschaftswerte von WPF- Objekten errechnen sich aus dem Kontext, in dem das WPF-Element steht. Der implementierende Mechanismus unterscheidet sich fundamental von den Bekannten Eigenschaften der CLR- Sprachen wie C#. Folgendes Bild skizziert die Funktionsweise der DependencyProperties von WPF






Rendern von WPF-Objektbäumen mit maximaler Hardwarebeschleunigung- Visual

Die durch DirectX angesteuerte Grafikhardware arbeitet nach einem "Maler"- Algorithmus: Zuerst werden die Elemente des Hintergrundes gezeichnet, dann darüber die Elemente des Vordergrundes (Kindelemente). Sind die Kindelemente zu einem bestimmten Teil transparent, dann wird dies durch die Grafikhardware beim überzeichnen realisiert.




DirextX basiert damit auf einem hierarchischen Modell. Die Knoten in dieser Hierarchie werden Strukturknoten genannt. Die Wurzel ist der gesamte Bildhintergrund, und die Blattelemente stehen unmittelbar im Vordergrund.

Visual Basisklasse

Die Visual Basisklasse ist vergleichbar mit einer Fensterhandle in Win32: Sie zeigt auf eine Menge von Strukturknoten im milcore, aus denen das von Visual abgeleitete WPF- Objekt gerendert wird.




Layout-Modelle und innovative Ereignisverarbeitung: UIElement

Die Basisklasse UIElement erweitert die WPF um folgende Funktionen:

  1. Layout-Modelle

  2. Verarbeitung von GUI- Ereignissen

Layout-Modelle

Kind – Steuerelemente können in der WPF nach beliebigen Regeln auf der Präsentationsoberfläche angeordnet werden. Dieses flexible Layout wird durch einen zweistufigen Prozess erreicht, den die Basisklasse UIElement implementiert.

Stufe

Operation

Details

1

UIElement.Measure(Size availableSize)

Die Methode wird von dem Elternelement aufgerufen. Innerhalb des zur Verfügung stehenden Rechtecksfläche werden die benötigte Rechtecksfläche bestimmt, und in der Eigenschsft DesiredSize bereitgestellt.

Grundsätzlich wird nur eine Fläche beansprucht, die minimal zur Darstellung des Inhaltes vom Steuerelement benötigt wird.

2

UIElement.Arrange(Rect finalRect)

Die Kindelemente werden innerhalb der zur Verfügung stehenden Rechteckfläche neu angeordnet.

In der WPF werden bereits spezielle Implementierungen für Layouts in Form von Container- Klassen mitgeliefert wie Grid und WrapPanel.

Verarbeitung von GUI- Ereignissen

Durch eingaben auf der Benutzeroberfläche werden im Windows Betriebssystem User32 Nachrichten generiert und an die Nachrichtenwarteschlange der betroffenen Anwendung weitergeleitet. Ist die Anwendung eine WPF- Anwendung, dann werden die User32- Nachrichten in zwei WPF- Ereignisse konvertiert:

  1. Vorschauereignis

  2. tatsächliches Ereignis

Das Vorschauereignis wird dabei, von der WPF- Objektbaumwurzel beginnend, absteigend an jedes Element übergeben, das auf dem Weg zu dem Element liegt, das mit dem Fensterausschnitt auf dem Bildschirm korrespondiert, in dem die Eingabe ursprünglich stattfand. Diese Weiterleitung von der Wurzel zum Kindelement wird Tunnelprinzip genannt.

Das tatsächliche Ereignis wird zuerst an das betroffene Kindelement im Objektbaum ausgelöst, und dann aufsteigend bis zur Wurzel an alle Eltern- und Großelternelemente.

Resourcen verwalten mit FrameworkElement

XAML

Einführung

XAML ist das Akronym aus Extensible Application Markup Language. Es ist ein von der Firma Microsoft entwickeltes XML Vokabular, mit dem grafische Benutzeroberflächen beschrieben werden können.

Ursprünglich wurde XAML für die WPF- Bibliothek entwickelt. XAML ist auch unabhängig von .NET und WPF einsetzbar. So können einfache XAML- Dateien analog HTML Dateien von Browsern wie IE oder Firefox interpretiert und dargestellt werden. Grundlage dafür ist eine Aufteilung des Vokabulars bezüglich der Funktionalität durch XML- Namespaces:

Präsentation

Um die Oberfläche einer WPF- Anwendung zu Beschreiben, die im folgenden Namensraum eingeschlossene Teilmenge ausreichend:

<?xml version="1.0" encoding="utf-8" ?>
<StackPanel xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation" >
…
</StackPanel>

Präsentation und Anwendungslogik

Die Definition von z.B. von Eventhandler für Steuerelemente erfordert ein zusätzliches XAML- Vokabular. Dieses ist in den Namensraum mit dem Präfix x eingeschlossen.

<?xml version="1.0" encoding="utf-8" ?>
<StackPanel xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation" 
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Button Name="btnJava" Click="btnJava_Click" >Click mich</Button>
    <x:Code>
        <![CDATA[
                private void btnJava_Click(object sender, RoutedEventArgs e)
                {
                    MessageBox.Show("Hallo");
                }
            ]]>
    </x:Code>
</StackPanel>

Silverligth

Silverligth ist ein Browser- Plugin, das eine Teilmenge der WPF implementiert. So können Vektorgrafiken und Animationen für Webanwendungen, basierend auf .NET implementiert werden. Das XAML- Vokalbular für Silverlight ist eine Teilmenge des XAML- Vokabulares von WPF. Es ist in folgenden Namespace eingeschlossen:

<UserControl x:Class="SilverlightApplication1.Page"
         xmlns="http://schemas.microsoft.com/client/2007"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     <Grid x:Name="LayoutRoot" Background="White">
 
     </Grid>
</UserControl>