## 19.3 Allgemeine Eigenschaften der WPF-Komponenten Der weiter oben gezeigte Vererbungsbaum hat zur Folge, dass viele Eigenschaften und Methoden in allen Steuerelementen identisch sind. Um im weiteren Verlauf dieses Kapitels nicht zu jedem Steuerelement immer wieder die gemeinsamen Eigenschaften aufzuführen, sollen die wichtigsten an dieser Stelle genannt werden. ### 19.3.1 Die Eigenschaft »Content« Sehr viele Steuerelemente, zu denen auch Button zu rechnen ist, sind auf die Basisklasse ContentControl zurückzuführen, die ihrerseits selbst direkt aus Control abgeleitet ist. Damit erben die Schaltflächen die Eigenschaft Content, die vom Typ Object ist und genau ein Element enthalten kann. Content gehört zu den herausragenden Merkmalen der WPF-Komponenten und kann entweder ein Text oder auch ein beliebiges anderes Element sein. Geben Sie Eigenschaft Content ein anderes Element an, beispielsweise ein Grid oder ein StackPanel, kann dieses selbst wieder Container praktisch unzähliger Unterelemente sein. Den Gestaltungsmöglichkeiten werden damit keine Grenzen gesetzt. Betrachten wir daher an dieser Stelle exemplarisch eine Schaltfläche vom Typ Button. Die Eigenschaft Content der Schaltfläche beschreibt den Text, mit dem ein Button beschriftet wird. Sie können die Eigenschaft als Attribut angeben, also:
    <Button Content="OK"></Button>
Eine weitere Möglichkeit, den Inhalt des Buttons zu definieren, besteht darin, innerhalb des öffnenden und schließenden XAML-Tags den Text anzugeben:
    <Button>
      OK
    </Button>
Das Ergebnis ist bei beiden Schreibweisen identisch, der Button wird mit der Zeichenfolge »OK« beschriftet. Da aber der durch Content beschriebene Inhalt vom Typ Object ist, eröffnen sich noch weiterreichende Möglichkeiten. Im folgenden Beispielcode wird ein Bild anstelle eines Textes verwendet:
    <Button>
      <Image ... ></Image>
    </Button>
Die Einschränkung, dass nur ein Element innerhalb einer Schaltfläche definiert werden kann, lässt sich sehr einfach umgehen, indem Sie ein einfach ein Element einfügen, das seinerseits wieder selbst über mehrere Unterelemente verfügt.
    <Button>
      <StackPanel>
        <TextBox Width="100" Text=""></TextBox>
        <Image.ImageFailed..></Image>
      </StackPanel>
    </Button>
Damit sind den Gestaltungsmöglichkeiten keine Grenzen gesetzt. Es stellt sich nun die Frage, woher XAML weiß, dass der Inhalt zwischen dem ein- und ausleitendem Element der Eigenschaft Content zugeordnet werden soll. Die Antwort auf diese Frage ist in der Definition der Klasse ContentControl zu finden. In dieser wird mit dem Attribut ContentPropertyAttribute die Eigenschaft Content als diejenige festgelegt, die den Inhalt zwischen den Tags aufnehmen soll.
    [ContentPropertyAttribute("Content")]
    public class ContentControl : Control, IAddChild
    { ...}
Sie können nicht davon ausgehen, dass der Inhalt zwischen dem ein- und ausleitenden Tag immer einer Eigenschaft Content zugeordnet wird. Es kann sich auch um eine beliebige, andere Eigenschaft handeln. Als typisches Beispiel sei an dieser Stelle die Klasse TextBox angeführt, die als Content-Eigenschaft die eigene Property Text festlegt.
    [ContentPropertyAttribute("Text")]
    public class TextBox : TextBoxBase, IAddChild
    { ...}
### 19.3.2 Größe einer Komponente Ehe wir uns den Eigenschaften zur Festlegung der Komponentengröße widmen, ein paar allgemeine Worte. Meistens ist es nicht notwendig, die Abmessungen der Steuerelemente explizit festzulegen, ebenso wenig deren Position. Sie nehmen damit einer WPF-Anwendung ihre angestammte Anpassungsfähigkeit, selbst die optimale Größe und Lage eines Controls zu finden. Die Auswirkungen zeigen sich, wenn sich beispielsweise die Zeichenketten ändern, etwa bei der Lokalisierung einer Anwendung. Um einige Größen- oder auch Positionsangaben werden Sie nicht herumkommen, beispielsweise um die Startgröße eines Fensters oder die durch die Eigenschaften Padding und Margin beschriebenen Abstände (mehr dazu weiter unten). Auch die Maßeinheit für die Größen- und Positionsangaben sollten an dieser Stelle erwähnt werden. Für alle Angaben gelten sogenannte device-independent pixel, zu Deutsch geräteunabhängige Pixel. Diese Pixel sind mit einer Größe von 1/96 Zoll definiert. Arbeitet ein Anwender mit einer Darstellung von 96 DPI, entspricht das WPF-Pixel tatsächlich einem Pixel auf dem Monitor. Das gilt auch für die Einstellung der Schriftgröße in einer WPF-Anwendung.
Anmerkung
Die Maßeinheit DPI steht für dots per inch. Sie gibt an, wie viele Pixel pro Zoll auf dem Monitor angezeigt werden. Die tatsächliche Einstellung hängt von der Konfiguration ab.
Anzumerken ist neben dem neuen Einheitensystem, dass gegenüber der traditionellen Entwicklung einer Windows-Anwendung mit der WinForm-API die Maßangaben vom Typ Double sind. Mit der Einführung der WPF ist es erstmals möglich, Steuerelemente beliebig zu skalieren. Das hat zur Folge, dass ein Button, der eine Länge von einem Zoll auf einem kleinen Bildschirm hat, auch in der Länge von einem Zoll auf einem großen Bildschirm angezeigt wird – vorausgesetzt, die DPI-Einstellungen sind bei beiden Systemen identisch. Sie können die Skalierung einer WPF-Oberfläche sehr gut im Designer von Visual Studio testen. Dazu müssen Sie nur den Zoom-Regler links oben im Designer verstellen. Hierbei gilt: Ein höherer DPI-Wert wird durch eine Zoom-Einstellung größer 100 % simuliert. Kommen wir nach diesem Ausflug in die Grundlagen zurück zum eigentlichen Thema, der Größe der Steuerelemente, und betrachten wir hierzu einen Button. Wie alle anderen Steuerelemente hat der Button die Eigenschaften Width und Height. Stellen Sie diese nicht explizit ein, nimmt der Button automatisch die Größe an, die erforderlich ist, um seinen Inhalt (Content) darzustellen. Betrachten wir nun eine Schaltfläche innerhalb einer Panel-Komponente oder einer Zelle des Grid-Steuerelements. Hier wird der Button die komplette Breite und Höhe des Containers ausfüllen. Zurückzuführen ist dieses Verhalten auf die Eigenschaften HorizontalAlignment und VerticalAlignment, deren Vorgabeeinstellung Stretch ist. Wie die Schaltfläche letztendlich dargestellt wird, ist vom übergeordneten Layoutcontainer abhängig. In einem StackPanel beispielsweise wird der Button die komplette Breite des Stackpanels einnehmen. Hier wird HorizontalAlignment ausgewertet, während die Höhe des Buttons sich aus der Höhe seines Inhalts bestimmt. In einer Grid-Zelle hingegen werden beide Eigenschaften bewertet, sodass die Schaltfläche die Zelle komplett ausfüllt. Grenzfälle der Größenfestlegung gibt es natürlich auch. Stellen Sie sich nur eine TextBox-Komponente vor, die mit der Benutzereingabe in ihrer Breite wächst. Gleichermaßen kann es sein, dass Steuerelemente sich auf eine Breite von 0 reduzieren. Um diesen Extremen vorzubeugen, können Sie mit den Eigenschaften MinWidth, MaxWidth, MinHeight und MaxHeight die minimalen und maximalen Ausdehnungen eines Steuerelements begrenzen. ### 19.3.3 Ausrichtung einer Komponente Zur Ausrichtung einer Komponente in ihrem umgebenden Container dienen die beiden Eigenschaften HorizontalAlignment und VerticalAlignment. HorizontalAlignment kann die Werte Left, Right, Center und Stretch einnehmen, VerticalAlignment die Werte Top, Bottom, Center und Stretch. Verzichten Sie auf die explizite Angabe der beiden Eigenschaften, gilt die Einstellung Stretch. Eine solche Komponente würde, wäre sie innerhalb einer Grid-Zelle platziert, die Zelle komplett ausfüllen. In Abbildung 19.3 sind die Auswirkungen der verschiedenen Einstellungen zu sehen. Der Abbildung liegt der folgende XAML-Code zugrunde:
    <Grid ShowGridLines="True">
      <Grid.RowDefinitions>
        <RowDefinition /><RowDefinition /><RowDefinition /><RowDefinition />
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition /><ColumnDefinition />
      </Grid.ColumnDefinitions>
      <Button Grid.Row="0" VerticalAlignment="Top">Button1</Button>
      <Button Grid.Row="1" VerticalAlignment="Bottom">Button2</Button>
      <Button Grid.Row="2" VerticalAlignment="Center">Button3</Button>
      <Button Grid.Row="3">Button4</Button>
      <Button Grid.Row="0" Grid.Column="1"
              HorizontalAlignment="Left">Button5</Button>
      <Button Grid.Row="1" Grid.Column="1"
              HorizontalAlignment="Right">Button6</Button>
      <Button Grid.Row="2" Grid.Column="1"
              HorizontalAlignment="Center">Button7</Button>
      <Button Grid.Row="3" Grid.Column="1" >Button8</Button>
    </Grid>
Hier klicken, um das Bild zu vergrößern Abbildung 19.3 Ausrichtung mit HorizontalAlignment und VerticalAlignment Wenn wir uns allgemein über die Ausrichtung unterhalten, müssen wir auch die Ausrichtung des Inhalts innerhalb eines Steuerelements berücksichtigen. Dieser wird durch die beiden Eigenschaften HorizontalContentAlignment VerticalContentAlignment beschrieben. Beide ermöglichen Einstellungen, die den Werten entsprechen, die weiter oben schon beschrieben worden sind. ### 19.3.4 Die Eigenschaften »Padding« und »Margin« Fügen Sie eine Schaltfläche in ein StackPanel ein, wird die Schaltfläche die gesamte vom StackPanel zur Verfügung gestellte Breite in Anspruch nehmen. Der Button erstreckt sich also vom linken bis zum rechten Rand des StackPanels. Die Höhe der Schaltfläche wiederum wird genau so sein, dass der Inhalt der Schaltfläche dargestellt werden kann (siehe dazu Abbildung 19.4). Hier klicken, um das Bild zu vergrößern Abbildung 19.4 Standardanordnung zweier Schaltflächen im Stackpanel Diese doch sehr eingezwängt anmutende Darstellung kann mit den beiden sich sehr ähnlichen Eigenschaften Margin und Padding beeinflusst werden, die zusätzlichen Freiraum zur Verfügung stellen. Der Unterschied zwischen Margin und Padding ist der, dass Margin den Freiraum außerhalb eines Steuerelements beeinflusst und Padding den Freiraum innerhalb des Elements. Abbildung 19.5 verdeutlicht die Unterschiede zwischen Padding und Margin. Der Abbildung liegt der folgende XAML-Code zugrunde. Beachten Sie, dass für Button1 nur Margin (Außenrand), und für Button2 nur Padding (Innenrand) eingestellt ist.
    <StackPanel>
      <Button Margin="10">Button1</Button>
      <Button Padding="20">Button2</Button>
    </StackPanel>
Hier klicken, um das Bild zu vergrößern Abbildung 19.5 Die Eigenschaften »Padding« und »Margin« Im Beispiel wirken sich die Angaben für Margin und Padding auf alle vier Ränder gleichermaßen aus. Sie können aber auch zwei andere Varianten benutzen, um die Randabstände unterschiedlich festzulegen. Mit
    Margin="10 30"
wird der linke und rechte Außenrand mit 10 Einheiten festgelegt, mit dem Wert 30 der Außenrand oben und unten. Wenn Sie vier Werte angeben, z. B.
    Margin="10 20 30 40"
dann wird der linke Randabstand mit 10 Einheiten festgelegt, danach folgt der obere Randabstand mit 20 Einheiten, der rechte mit 30 und letztendlich der untere mit 40. Padding und Margin sind vom Typ System.Windows.Thickness und haben den Datentyp Double. Thickness hat nur zwei Konstruktoren: einen einfach und einen vierfach parametrisierten, der wie folgt aufgerufen wird:
    Button1.Margin = new Thickness(12, 20, 30, 40);
### 19.3.5 Sichtbarkeit eines Steuerelements Die Eigenschaft Visibility gibt an, ob ein Steuerelement sichtbar ist oder nicht. Normalerweise würde man dahinter einen booleschen Datentyp vermuten, der mit true und false die Sichtbarkeit steuert. In WPF ist das nicht der Fall, denn Visibility erlaubt Einstellungen, die in der Enumeration Visibility definiert sind.

Tabelle 19.2 Die Werte der Enumeration »Visibility«

Wert | Beschreibung
Visible | Das Steuerelement ist sichtbar.
Hidden | Das Steuerelement ist unsichtbar, beansprucht aber weiterhin den ihm angestammten Platz.
Collapsed | Das Steuerelement ist unsichtbar und hat die Größe 0. Andere Steuerelemente können den freigegebenen Platz nutzen.
Der Unterschied zwischen den Werten Hidden und Collapsed zeigt das folgende Listing. Button1 ist Hidden, behält aber seine Größe und Position bei. Button3 hingegen ist Collapsed. Die darunter liegende Schaltfläche Button4 rutscht nach oben und nimmt die Position von Button3 ein (siehe auch Abbildung 19.6).
    <StackPanel>
      <Button Padding="10" Visibility="Hidden">Button1</Button>
      <Button Padding="10">Button2</Button>
      <Button Padding="10" Visibility="Collapsed">Button3</Button>
      <Button Padding="10">Button4</Button>
    </StackPanel>
Hier klicken, um das Bild zu vergrößern Abbildung 19.6 Auswirkungen der Einstellung der Eigenschaft »Visibility« ### 19.3.6 Farbeinstellungen Die Vorder- und Hintergrundfarbe wird bei den Steuerelementen mit den Eigenschaften Foreground und Background eingestellt. Beide Eigenschaften sind vom Typ Brush. Bei Brush handelt es sich um eine abstrakte Klasse, folglich kommt als konkrete Angabe nur eine der Ableitungen infrage. Hierbei handelt es sich um die in Tabelle 19.3 aufgeführten sechs Klassen.

Tabelle 19.3 Die abgeleiteten Klassen von »Brush«

Klasse | Beschreibung
SolidColorBrush | Beschreibt eine einheitliche Farbe.
ImageBrush | Zeichnet ein Bild in den entsprechenden Bereich. Das Bild kann entweder skaliert oder mehrfach gezeichnet werden.
DrawingBrush | Entspricht ImageBrush mit dem Unterschied, dass anstelle einer Bitmap eine Vektorgrafik gezeichnet wird.
LinearGradientBrush | Beschreibt einen linearen Farbverlauf zwischen zwei oder noch mehr Farben.
RadialGradientBrush | Zeichnet einen kreisförmigen Übergang zwischen zwei oder mehr Farben.
VisualBrush | Zeichnet ein Visual-Objekt in den angegeben Bereich.
Auf eine weitere Beschreibung dieser Klassen soll an dieser Stelle verzichtet werden. Wir werden das in Kapitel 22, »2D-Grafik«, noch nachholen. ### 19.3.7 Schriften Lassen Sie uns an dieser Stelle auch noch über die Festlegung der Schrift sprechen. Zunächst einmal ist festzuhalten, dass alle Steuerelemente die Einstellungen der Schrift von ihrem übergeordneten Container übernehmen. Ändern Sie beispielsweise die Schriftart in Window, werden alle Steuerelemente des Fensters automatisch den Fonttyp übernehmen, es sei denn, Sie legen die Schriftart für ein Steuerelement anders fest. Die Schrift kann über insgesamt fünf Eigenschaften manipuliert werden.

Tabelle 19.4 Eigenschaften eines Fonts

Eigenschaft | Beschreibung
FontFamily | FontFamily gibt die Schriftart an. Dabei handelt es sich ausschließlich um TrueType-Schriften. Die Vorgabe ist Segoe UI.
FontSize | Mit FontSize wird die Schriftgröße in WPF-Pixeln angegeben.
FontStretch | FontStretch gibt an, ob eine Schrift zusammengedrückt oder gestreckt angezeigt werden soll. Die Eigenschaft lässt mehrere Einstellungen zu, wird aber nicht von jeder Schriftart unterstützt.
FontStyle | FontStyle gibt an, ob eine Schrift normal oder kursiv dargestellt wird.
FontWeight | Die Eigenschaft beschreibt, wie fett die Schrift dargestellt werden soll. Im Gegensatz zu den Einstellungen unter WinForms (true oder false), sind unter WPF sehr viele Grade einstellbar, die aber nicht von allen Schriftarten gleichermaßen unterstützt werden.