Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort zur 5. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Weitere .NET-Datentypen
7 Weitere Möglichkeiten von C#
8 Auflistungsklassen (Collections)
9 Fehlerbehandlung und Debugging
10 LINQ to Objects
11 Multithreading und die Task Parallel Library (TPL)
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 Einige wichtige .NET-Klassen
15 Projektmanagement und Visual Studio 2010
16 XML
17 WPF – Die Grundlagen
18 WPF-Containerelemente
19 WPF-Steuerelemente
20 Konzepte der WPF
21 Datenbindung
22 2D-Grafik
23 ADO.NET – verbindungsorientierte Objekte
24 ADO.NET – Das Command-Objekt
25 ADO.NET – Der SqlDataAdapter
26 ADO.NET – Daten im lokalen Speicher
27 ADO.NET – Aktualisieren der Datenbank
28 Stark typisierte DataSets
29 LINQ to SQL
30 Weitergabe von Anwendungen
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual C# 2010 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2010

Visual C# 2010
geb., mit DVD
1295 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1552-7
Pfeil 20 Konzepte der WPF
Pfeil 20.1 Ressourcen
Pfeil 20.1.1 Wo logische Ressourcen definiert werden können
Pfeil 20.1.2 Definition logischer Ressourcen
Pfeil 20.1.3 Statische und dynamische Ressourcen
Pfeil 20.1.4 Ressourcen in Ressourcendateien
Pfeil 20.1.5 Suche nach einer Ressource
Pfeil 20.1.6 Ressourcen mit C#-Code
Pfeil 20.1.7 Abrufen von Systemressourcen
Pfeil 20.2 Styles
Pfeil 20.2.1 Einfache Stile
Pfeil 20.2.2 Typisierte Stile
Pfeil 20.2.3 EventSetter
Pfeil 20.3 Trigger
Pfeil 20.3.1 Eigenschaftstrigger
Pfeil 20.3.2 Ereignistrigger
Pfeil 20.3.3 Datentrigger
Pfeil 20.4 Templates
Pfeil 20.4.1 Grundlagen der Templates
Pfeil 20.4.2 Verfeinerung des Entwurfs
Pfeil 20.4.3 Definition innerhalb eines Styles
Pfeil 20.4.4 Den Visual Tree ermitteln
Pfeil 20.5 Commands
Pfeil 20.5.1 Vordefinierte Commands
Pfeil 20.5.2 Beispielanwendung
Pfeil 20.5.3 Commando-Ziel festlegen
Pfeil 20.5.4 Commands an Ereignisse binden
Pfeil 20.5.5 Commands programmieren


Galileo Computing - Zum Seitenanfang

20.2 Styles Zur nächsten ÜberschriftZur vorigen Überschrift

Das Layout grafischer Komponenten können Sie nahezu beliebig im XAML-Code konfigurieren. Das Einstellen der individuellen Eigenschaften für Font, Farbe, Größe usw. ist aber mit einem nicht unbeträchtlichen Aufwand verbunden. Insbesondere dann, wenn mehrere Steuerelemente einheitlich gestaltet werden sollen, ist das Endergebnis eine riesige XAML-Datei, in der die Einstellungen der Controls redundant auftreten. An dieser Stelle betreten die Styles die Bühne. Styles gestatten das Zusammenfassen mehrerer Einstellungen, die zentral zur Verfügung gestellt werden.

Das Prinzip erinnert an das von CSS (Cascading Style Sheets) in HTML. Allerdings werden Styles nicht in separaten Dateien verpackt, sondern als logische Ressourcen angeboten. Styles können lokal im Fenster, in der App.xaml-Datei oder in einem externen Ressourcenwörterbuch bereitgestellt werden. Weil Styles in der Regel dazu benutzt werden, der Anwendung ein einheitliches, leicht und zentral änderbares Layout zu geben, scheidet in den meisten Fällen die lokale Definition in einem Fenster aus.


Galileo Computing - Zum Seitenanfang

20.2.1 Einfache Stile Zur nächsten ÜberschriftZur vorigen Überschrift

Das Prinzip einer Stil-Definition soll sofort an einem Beispiel gezeigt werden. Nehmen wir dazu zunächst an, Sie möchten ein Fenster bereitstellen, in dem sich drei Schaltflächen befinden. Alle Schaltflächen sollen als besonderes Design einen Farbverlauf haben, der mittels XAML-Code in jeder der drei Schaltflächen angegeben wird.


...
<Button Height="35">
  <Button.Background>
    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
      <GradientStop Offset="0.0" Color="Red" />
      <GradientStop Offset="1.0" Color="LightCyan" />
    </LinearGradientBrush>
  </Button.Background>
  <Button.FontSize>18</Button.FontSize>
         Button1
</Button>
<Button Height="35">
  <Button.Background>
    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
      <GradientStop Offset="0.0" Color="Red" />
      <GradientStop Offset="1.0" Color="LightCyan" />
    </LinearGradientBrush>
  </Button.Background>
  <Button.FontSize>18</Button.FontSize>
         Button2
</Button>
<Button Height="35">
  <Button.Background>
    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
      <GradientStop Offset="0.0" Color="Red" />
      <GradientStop Offset="1.0" Color="LightCyan" />
    </LinearGradientBrush>
  </Button.Background>
  <Button.FontSize>18</Button.FontSize>
         Button3
</Button>

Das Problem des redundanten Codes wird in diesem kleinen Beispiel bereits offensichtlich, denn bis auf die Beschriftung ist der Code für alle drei Schaltflächen identisch. Zudem wirkt der XAML-Code unübersichtlich.

Die Gemeinsamkeiten der drei Schaltflächen sollen nun von einem Stil (Style) beschrieben werden, der von den Schaltflächen gemeinsam genutzt wird. Stile werden in Resource-Abschnitten definiert. Daher bieten sich insgesamt vier Bereitstellungsorte an:

  • Styles können direkt im Element angegeben werden. Allerdings ist das eher eine theoretische Option, die ausscheidet, da der Stil nur von der betreffenden Komponente genutzt werden könnte.
  • Etwas besser ist es, Stile im Resources-Abschnitt des Window-Objekts anzugeben. Die Nutzbarkeit ist so auf das aktuelle Fenster beschränkt, andere Fenster können von dem Stil allerdings nicht profitieren. Eine Ausnahme wäre beispielsweise, wenn es sich bei dem Fenster um das Hauptfenster der Anwendung handeln würde, dem alle anderen Fenster untergeordnet sind.
  • Damit alle Komponenten eines Programms von einer Style-Definition gleichermaßen profitieren können, sollten Sie diese global beschreiben. Dafür eignet sich die Datei App.xaml oder ein externes Ressourcenwörterbuch.

Nun sollten wir uns zuerst die Lösung mit einer Style-Definition ansehen.


// ------------------------------------------------------------------
// Beispiel: ...\Kapitel 20\SimpleStyle
// ------------------------------------------------------------------
<Window x:Class="SimpleStyle.MainWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="SimpleStyle" Height="180" Width="300">
  <StackPanel>
   <Button Style="{StaticResource btnStyle}">
       Button1
   </Button>
   <Button Style="{StaticResource btnStyle}">
       Button2
   </Button>
   <Button Style="{StaticResource btnStyle}">
       Button3
   </Button>
  </StackPanel>
</Window>
// Datei App.xaml
<Application x:Class="SimpleStyle.App" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     StartupUri="MainWindow.xaml">
  <Application.Resources>
    <Style x:Key="btnStyle">
      <Setter Property="Control.Height" Value="35" />
      <Setter Property="Control.FontSize" Value="18" />
      <Setter Property="Control.Background">
        <Setter.Value>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <GradientStop Offset="0.0" Color="Red" />
            <GradientStop Offset="1.0" Color="LightCyan" />
          </LinearGradientBrush>
        </Setter.Value>
      </Setter>
    </Style>
  </Application.Resources>
</Application>

Abbildung 20.4 Ausgabe des Beispielprogramms »SimpleStyle«

Stile werden als logische Ressourcen definiert und durch das Element Style beschrieben. Mit x:Key erhält jeder Style einen Schlüssel, unter dem er aufrufbar ist:


<Style x:Key="btnStyle">

Die einzelnen Eigenschaften werden durch Setter-Elemente beschrieben. Deren Attribut Property geben Sie die Eigenschaft an, die der Stil beschreibt. Die Bezeichnung setzt sich aus dem Typ der Zielkomponente und dem Namen der Eigenschaft zusammen. Die Angabe ist notwendig, damit WPF die Klasse und die Abhängigkeitseigenschaft korrekt auflösen kann.


Hinweis

Es gibt eine Bedingung hinsichtlich der Eigenschaften, die in Setter Property genannt werden können: Es muss sich um eine Abhängigkeitseigenschaft (Dependency Property) handeln.


Über das Attribut Value teilen Sie den Wert mit, zum Beispiel:


<Setter Property="Control.Height" Value="35" />

Um komplexere Eigenschaftswerte zu definieren, können Sie beim Attribut Value auch auf die Eigenschaft-Element-Schreibweise zurückgreifen. Im unserem Beispiel oben wird das anhand der Eigenschaft Background gezeigt.

Da es sich bei einer Style-Definition um eine Ressource handelt, kann eine Komponente den Stil mit der Markup-Erweiterung StaticResource oder DynamicResource nutzen:


<Button Style="{StaticResource btnStyle}">

Die Ressource wird dabei dem Style-Attribut der Komponente mitgeteilt.


Galileo Computing - Zum Seitenanfang

20.2.2 Typisierte Stile Zur nächsten ÜberschriftZur vorigen Überschrift

Es ist möglich, bereits dem Element Style den Zieldatentyp bekannt zu geben, an den sich die Eigenschaftseinstellungen richten. Der Zieldatentyp wird mit dem Attribut TargetType angegeben, zum Beispiel:


<Style TargetType="{x:Type Button}">

Das Zielelement bereits in der Stildefinition zu nennen hat den Vorteil, dass die Steuerelemente dieses Typs den Stil nicht mehr referenzieren müssen, denn er wird automatisch auf alle Steuerelemente des entsprechenden Typs angewendet. Allerdings können Sie die damit frei gewordene Style-Eigenschaft eines Steuerelements nicht dazu benutzen, um einen weiteren Stil anzugeben.


// ------------------------------------------------------------------
// Beispiel: ...\Kapitel 20\TypisierterStil
// ------------------------------------------------------------------
<Window ... >
  <StackPanel>
   <Button>Button1</Button>
    <Button>Button2</Button>
    <Button>Button3</Button>
  </StackPanel>
</Window>
// Datei App.xaml
<Application ...>
  <Application.Resources>
    <Style TargetType="{x:Type Button}">
      <Setter Property="Control.Height" Value="35" />
      <Setter Property="Control.FontSize" Value="18" />
      <Setter Property="Control.Background">
        <Setter.Value>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <GradientStop Offset="0.0" Color="Red" />
            <GradientStop Offset="1.0" Color="LightCyan" />
          </LinearGradientBrush>
        </Setter.Value>
      </Setter>
    </Style>
  </Application.Resources>
</Application>

Möchten Sie, dass eine oder mehrere Komponenten nicht von der unter der TargetType-Angabe angegebenen Stil-Definition profitieren, legen Sie eine leere Stil-Definition an, die als Dummy dient, zum Beispiel:


<Style x:Key="DummyStyle" />

Diesen Stil geben Sie in der Style-Eigenschaft der betreffenden Komponente an, die dann in der Standarddarstellung angezeigt wird:


<Button Style="DummyStyle" ... />

Überschreiben einer Stildefinition

Geben Sie in einer Komponente eine Eigenschaft an, die in einem Stil ebenfalls definiert ist, überschreibt die Angabe in der Komponente den Stil. Ersetzen Sie die Definition des ersten Buttons im Beispiel oben mit


<Button Background="Beige">Button1</Button>

dann wird die Schaltfläche in Beige dargestellt.

Haben Sie Stile an mehreren Stellen definiert, zum Beispiel im Window und in der Datei App.xaml, wird der Stil angewendet, der in der Struktur am tiefsten liegt, also in diesem Fall derjenige, der im XAML-Code des Fensters definiert ist.

Erweitern von Styles

Styles lassen sich auch erweitern. Dazu erstellen Sie einen Stil, den Sie zum Beispiel MyStyle nennen. In einem zweiten Style geben Sie über das Attribut BasedOn den Ressourcentyp und den Namen des zu erweiternden Stils an. Bereits definierte
Eigenschaftswerte können bei diesem Verfahren auch überschrieben werden. Haben Sie im Basisstil TargetType angegeben, müssen Sie im abgeleiteten Stil ebenfalls eine TargetType-Angabe machen. Diese muss denselben oder einen abgeleiteten Typ beschreiben. Im folgenden Beispielprogramm wird das gezeigt.


// ---------------------------------------------------------
// Beispiel: ...\Kapitel 20\ErweiterterStil
// ---------------------------------------------------------
<Window ...>
  <Window.Resources>
    <Style x:Key="ButtonStyle">
      <Setter Property="Control.Height" Value="35" />
      <Setter Property="Control.FontSize" Value="18" />
      <Setter Property="Control.Background">
        <Setter.Value>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <GradientStop Offset="0.0" Color="Red" />
            <GradientStop Offset="1.0" Color="LightCyan" />
          </LinearGradientBrush>
        </Setter.Value>
      </Setter>
    </Style>
    <Style x:Key="NewButtonStyle" 
           BasedOn="{StaticResource ButtonStyle}">
      <Setter Property="Control.FontFamily" Value="Courier" />
      <Setter Property="Control.FontSize" Value="14" />
    </Style>
  </Window.Resources>
  <StackPanel>
    <Button Style="{StaticResource NewButtonStyle}">Button1</Button>
    <Button Style="{StaticResource ButtonStyle}">Button2</Button>
    <Button Style="{StaticResource NewButtonStyle}">Button3</Button>
  </StackPanel>
</Window>

Der Einfachheit halber sind in diesem Beispiel beide Styles im Resources-Abschnitt des Fensters definiert. Der zuerst aufgeführte Stil ButtonStyle legt neben der Höhe des Steuerelements dessen Schriftfarbe und Hintergrunddarstellung fest. Der zweite Stil, NewButtonStyle, übernimmt die Vorgaben des ersten Stils, erweitert um die Vorschrift der Schriftart.

Im erweiternden Style darf auch eine Eigenschaft angeführt werden, die im Basisstil bereits definiert ist. Der erweiternde Stil überdeckt dann den geerbten Wert. Im Beispiel wird das anhand der Eigenschaft FontSize gezeigt.

Abbildung 20.5 zeigt die Ausgabe des Beispiels. Dass der Wert für die Schriftgröße der oberen und der unteren Schaltfläche überschrieben wurde, ist hier deutlich zu erkennen.

Abbildung 20.5 Ausgabe des Beispielprogramms »ErweiterterStil«


Galileo Computing - Zum Seitenanfang

20.2.3 EventSetter topZur vorigen Überschrift

Bei der Verwendung von Stilen steht Ihnen auch das Objekt EventSetter zur Verfügung. Mit einem EventSetter können Sie allen Elementen eines Typs einen Ereignishandler zuordnen. Die Zuordnung gilt dann für alle Komponenten, die die Style-Definition nutzen. Bei den Ereignissen muss es sich um RoutedEvents handeln. Die Definition eines EventSetters lautet wie folgt:


<Style>
  <EventSetter Event="..." Handler="..." />
</Style>

Dem Attribut Event wird das Ereignis genannt, dem Attribut Handler der entsprechende Ereignishandler. Registrieren Sie sowohl im Stil einen Ereignishandler als auch direkt im XAML-Code der Komponente, werden beide ausgeführt. Dabei kommt es immer zuerst zu der Ausführung des Ereignishandlers, der in der Komponente direkt angegeben ist.

Im folgenden Beispiel enthält ein StackPanel zwei ListBoxen sowie zwei in einem Grid positionierte TextBoxen. Die Listboxen werden an einen Stil gebunden, in dem das Ereignis SelectionChanged der ListBoxen mit einem Ereignishandler verknüpft wird. Dieses Ereignis wird im XAML-Code der unteren ListBox außerdem mit einem weiteren Ereignishandler verknüpft. Der den beiden ListBoxen gemeinsame Ereignishandler schreibt den Inhalt des selektierten Elements in die linke TextBox, der zusätzliche Ereignishandler der unteren ListBox schreibt darüber hinaus in die rechte.


// ---------------------------------------------------------
// Beispiel: ...\Kapitel 20\EventSetter
// ---------------------------------------------------------
<Window ... >
<Window.Resources>
  <Style x:Key="listboxStyle">
    <EventSetter Event="ListBox.SelectionChanged"            
                 Handler="listbox1_SelectionChanged" />
  </Style>
</Window.Resources>
<StackPanel>
  <ListBox Margin="10" Background="AntiqueWhite" 
           Style="{StaticResource listboxStyle}" Name="listbox1" 
                    SelectionChanged="listbox1_SelectionChanged">
    <ListBoxItem>Australien</ListBoxItem>
    <ListBoxItem>Thailand</ListBoxItem>
    <ListBoxItem>Seychellen</ListBoxItem>
  </ListBox>
  <ListBox Margin="10" Background="LightSkyBlue" 
           Style="{StaticResource listboxStyle}" Name="listbox2"
           SelectionChanged="listbox2_SelectionChanged" >
    <ListBoxItem>Hamburg</ListBoxItem>
      <ListBoxItem>München</ListBoxItem>
      <ListBoxItem>Berlin</ListBoxItem>
    </ListBox>   
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition></ColumnDefinition>
        <ColumnDefinition></ColumnDefinition>
      </Grid.ColumnDefinitions>
      <TextBox Grid.Row="0" Grid.Column="0" Margin="5" 
               Name="txtLinks" Background="AliceBlue">
               ...
      </TextBox>
      <TextBox Grid.Row="0" Grid.Column="1" Margin="5"                    
               Name="txtRechts" Background="AliceBlue">
               ...
      </TextBox>
    </Grid>
  </StackPanel>
</Window>

Der Code in der CodeBehind-Datei enthält die beiden Ereignishandler mit dem folgenden Code:


public partial class MainWindow : Window {
  private void listbox1_SelectionChanged(...) {
    ListBox lst = (ListBox)sender;
    txtLinks.Text = ((ListBoxItem)lst.SelectedItem).Content.ToString();
  }
  private void listbox2_SelectionChanged(...) {
    ListBox lst = (ListBox)sender;
    txtRechts.Text = ((ListBoxItem)lst.SelectedItem).Content.ToString();
  }
}



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Visual C# 2010

Visual C# 2010
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Katalog: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


Zum Katalog: C/C++






 C/C++


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2010
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern