Erstellen von Formaten und Vorlagen

Aktualisiert: November 2007

Formate und Vorlagen von Windows Presentation Foundation (WPF) beziehen sich auf eine Suite von Features (Formate, Vorlagen, Trigger und Storyboards), mit denen die Designer einer Anwendung, eines Dokuments oder einer Benutzeroberfläche (user interface, UI) visuell überzeugende Effekte erzeugen und die Standardisierung auf ein einheitliches Erscheinungsbild ihres Produkts erreichen. Ein Autor oder Designer hat zahlreiche Möglichkeiten, die Darstellung von Anwendungen individuell zu gestalten. Allerdings ist ein striktes Modell für Formate und Vorlagen notwendig, um das Erscheinungsbild innerhalb einer Anwendung oder zwischen Anwendungen verwalten und gemeinsam nutzen zu können. Dieses Modell bietet Windows Presentation Foundation (WPF).

Ein anderes Feature des Formatierungsmodells von WPF ist die Trennung von Darstellung und Logik. Dies bedeutet, dass Designer das Erscheinungsbild einer Anwendung nur mit XAML ändern können, während gleichzeitig Entwickler die Programmierlogik mit C# oder Visual Basic bearbeiten.

In dieser Übersicht geht es um die Anwendung Einführung zum Beispiel zu Stilen und Vorlagen, die über zwei TextBlock-Elemente und ein ListBox-Steuerelement verfügt, das an eine Liste mit Bildern gebunden wird:

Formatierte ListView

Es werden keine Datenbindungskonzepte erläutert, sondern es geht vornehmlich um Formate und Vorlagen in Anwendungen. Informationen zur Datenbindung finden Sie unter Übersicht über Datenbindung.

Darüber hinaus sollten Sie mit Ressourcen vertraut sein, da diese eine Wiederverwendung von Formaten und Vorlagen ermöglichen. Weitere Informationen zu Ressourcen finden Sie unter Übersicht über Ressourcen.

Dieses Thema enthält folgende Abschnitte.

  • Grundlagen zu Formaten
  • Datenvorlagen
  • Steuerelementvorlagen
  • Trigger
  • Freigegebene Ressourcen und Designs
  • Verwandte Abschnitte

Grundlagen zu Formaten

Stellen Sie sich Style als bequeme Möglichkeit vor, um eine Reihe von Eigenschaftswerten auf mehrere Elemente anzuwenden. Betrachten Sie beispielsweise die folgenden TextBlock-Elemente und ihre Standarddarstellung:

<TextBlock>My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>

Bildschirmabbildung für Formatierungsbeispiel

Sie können die Standarddarstellung ändern, indem Sie Eigenschaften wie FontSize und FontFamily für jedes TextBlock-Element direkt festlegen. Wenn die TextBlock-Elemente einige Eigenschaften gemeinsam nutzen sollen, können Sie im Resources-Abschnitt der XAML-Datei ein Style erstellen, wie im Folgenden gezeigt:

<Window.Resources>


...


<!--A Style that affects all TextBlocks-->
<Style TargetType="TextBlock">
  <Setter Property="HorizontalAlignment" Value="Center" />
  <Setter Property="FontFamily" Value="Comic Sans MS"/>
  <Setter Property="FontSize" Value="14"/>
</Style>


...


</Window.Resources>

Wenn Sie TargetType des Formats auf den TextBlock-Typ festlegen, wird das Format auf alle TextBlock-Elemente im Fenster angewendet.

Die TextBlock-Elemente werden nun folgendermaßen angezeigt:

Bildschirmabbildung für Formatierungsbeispiel

Dieser Abschnitt enthält folgende Unterabschnitte.

  • Erweitern von Formaten
  • Beziehung zwischen der TargetType-Eigenschaft und dem x:Key-Attribut
  • Formate und Ressourcen
  • Programmgesteuertes Festlegen von Formaten
  • Bindungen, dynamische Ressourcen und Ereignishandler

Erweitern von Formaten

Sie könnten beispielsweise vorsehen, dass die beiden TextBlock-Elemente dieselben Eigenschaftenwerte verwenden sollen, wie FontFamily und die zentrierte HorizontalAlignment, und dass gleichzeitig der Text "My Pictures" zusätzliche Eigenschaften haben soll. Dazu können Sie ein neues Format erstellen, das auf dem ersten Format basiert, wie nachfolgend gezeigt:

<Window.Resources>


...


<!--A Style that extends the previous TextBlock Style-->
<!--This is a "named style" with an x:Key of TitleText-->
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
       TargetType="TextBlock"
       x:Key="TitleText">
  <Setter Property="FontSize" Value="26"/>
  <Setter Property="Foreground">
  <Setter.Value>
      <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
        <LinearGradientBrush.GradientStops>
          <GradientStop Offset="0.0" Color="#90DDDD" />
          <GradientStop Offset="1.0" Color="#5BFFFF" />
        </LinearGradientBrush.GradientStops>
      </LinearGradientBrush>
    </Setter.Value>
  </Setter>
</Style>


...


</Window.Resources>

Beachten Sie, dass das oben genannte Format x:Key erhält. Zum Anwenden des Formats legen Sie die Style-Eigenschaft von TextBlock auf den x:Key-Wert fest, wie nachfolgend gezeigt:

<TextBlock Style="{StaticResource TitleText}" Name="textblock1">My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>

Dieses TextBlock-Format hat nun einen HorizontalAlignment-Wert von Center, einen FontFamily-Wert von Comic Sans MS, einen FontSize-Wert von 26 und einen Foreground-Wert, der auf LinearGradientBrush festgelegt ist, wie im Beispiel veranschaulicht. Beachten Sie, dass der FontSize-Wert des Basisformats überschrieben wurde. Wenn mehrere Setter dieselbe Eigenschaft in Style festlegen, hat der zuletzt deklarierte Setter Vorrang.

Im folgenden Beispiel wird gezeigt, wie die TextBlock-Elemente nun dargestellt werden:

Formatierte TextBlocks

Durch dieses TitleText-Format wird das für den TextBlock-Typ erstellte Format erweitert. Sie können auch ein Format erweitern, das über einen x:Key verfügt, indem Sie den x:Key-Wert verwenden. Ein entsprechendes Beispiel ist das für die BasedOn-Eigenschaft zur Verfügung gestellte Beispiel.

Beziehung zwischen der TargetType-Eigenschaft und dem x:Key-Attribut

Wenn Sie die TargetType-Eigenschaft auf TextBlock festlegen, ohne das Format x:Key zuzuweisen, wird es auf alle TextBlock-Elemente angewendet, wie im ersten Beispiel gezeigt. In diesem Fall wird x:Key implizit auf {x:Type TextBlock} festgelegt. Dies bedeutet, dass Style nicht automatisch auf alle TextBlock-Elemente angewendet wird, wenn Sie den x:Key-Wert explizit nicht auf {x:Type TextBlock} festlegen. Stattdessen müssen Sie das Format explizit auf die TextBlock-Elemente anwenden (indem Sie den x:Key-Wert verwenden). Wenn sich das Format im Ressourcenabschnitt befindet und Sie die TargetType-Eigenschaft nicht für das Format festlegen, müssen Sie x:Key angeben.

Die TargetType-Eigenschaft gibt nicht nur einen Standardwert für x:Key an, sondern legt auch fest, auf welchen Typ die Settereigenschaften angewendet werden. Wenn Sie TargetType nicht angeben, müssen Sie die Eigenschaften in den Setter-Objekten mit einem Klassennamen qualifizieren. Dazu verwenden Sie die Syntax Property="ClassName.Property". Statt Property="FontSize" festzulegen, müssen Sie beispielsweise Property auf "TextBlock.FontSize" oder "Control.FontSize" festlegen.

Beachten Sie außerdem, dass viele WPF-Steuerelemente aus einer Kombination von anderen WPF-Steuerelementen bestehen. Das Erstellen eines Formats, das auf alle Steuerelemente eines Typs angewendet wird, kann zu unerwarteten Ergebnissen führen. Wenn Sie z. B. ein Format erstellen, das sich auf den TextBlock-Typ in Window bezieht, wird das Format auf alle TextBlock-Steuerelemente im Fenster angewendet, auch wenn TextBlock Teil eines anderen Steuerelements ist, z. B. von ListBox.

Formate und Ressourcen

Sie können ein Format für jedes Element verwenden, das von FrameworkElement oder FrameworkContentElement abgeleitet ist. Ein Format wird meist als Ressource im Resources-Abschnitt in einer XAML-Datei deklariert, wie in den vorhergehenden Beispielen gezeigt. Da es sich bei Formaten um Ressourcen handelt, unterliegen sie den gleichen Bereichsregeln, die für alle Ressourcen gelten. Wo Sie ein Format deklarieren, hat also Auswirkungen darauf, wo es angewendet werden kann. Wenn Sie das Format z. B. im Stammelement der XAML-Datei der Anwendungsdefinition deklarieren, kann das Format überall in der Anwendung verwendet werden. Wenn Sie eine Navigationsanwendung erstellen und das Format in einer der XAML-Dateien der Anwendung deklarieren, kann das Format nur in dieser XAML-Datei verwendet werden. Weitere Informationen zu Bereichsregeln für Ressourcen finden Sie unter Übersicht über Ressourcen.

Außerdem finden Sie weitere Informationen zu Formaten und Ressourcen unter Gemeinsam genutzte Ressourcen und Designs weiter unten in dieser Übersicht.

Programmgesteuertes Festlegen von Formaten

Wenn Sie einem Element programmgesteuert ein benanntes Format zuweisen möchten, rufen Sie das Format aus der Ressourcenauflistung ab und weisen es der Style-Eigenschaft des Elements zu. Beachten Sie, dass die Elemente in einer Ressourcenauflistung vom Typ Object sind. Aus diesem Grund müssen Sie das abgerufene Format in Style umwandeln, bevor Sie es der Style-Eigenschaft zuweisen. Gehen Sie beispielsweise folgendermaßen vor, um das definierte TitleText-Format auf TextBlock mit dem Namen textblock1 festzulegen:

textblock1.Style = (Style)(this.Resources["TitleText"]);

Sobald ein Format angewendet wurde, ist es versiegelt und kann nicht mehr geändert werden. Wenn Sie ein bereits angewendetes Format dynamisch ändern möchten, müssen Sie ein neues Format erstellen, um das vorhandene zu ersetzen. Weitere Informationen finden Sie in den Ausführungen zur IsSealed-Eigenschaft.

Sie können ein Objekt erstellen, das das anzuwendende Format auf Grundlage benutzerdefinierter Logik auswählt. Ein entsprechendes Beispiel ist das für die StyleSelector-Klasse zur Verfügung gestellte Beispiel.

Bindungen, dynamische Ressourcen und Ereignishandler

Beachten Sie, dass Sie mit der Setter.Value-Eigenschaft eine Bindung als Markuperweiterung oder eine DynamicResource-Markuperweiterung angeben können. Weitere Informationen bieten die Beispiele für die Setter.Value-Eigenschaft.

Bisher wurde nur erläutert, wie Sie mit Settern einen Eigenschaftenwert festlegen können. Sie können auch Ereignishandler in einem Format angeben. Weitere Informationen finden Sie unter EventSetter.

Datenvorlagen

In dieser Beispielanwendung ist ein ListBox-Steuerelement an eine Liste von Fotos gebunden:

<ListBox ItemsSource="{Binding Source={StaticResource MyPhotos}}"
         Background="Silver" Width="600" Margin="10" SelectedIndex="0"/>

Dieses ListBox sieht zurzeit folgendermaßen aus:

ListBox vor dem Anwenden einer Vorlage

Die meisten Steuerelemente verfügen über Inhalte, die häufig aus den Daten abgerufen werden, an die Sie eine Bindung herstellen. In diesem Beispiel sind die Daten die Liste von Fotos. In WPF definieren Sie die visuelle Darstellung der Daten mithilfe von DataTemplate. Grundsätzlich bestimmen Sie durch die Inhalte von DataTemplate, wie die Daten in der gerenderten Anwendung dargestellt werden.

In der Beispielanwendung hat jedes benutzerdefinierte Photo-Objekt eine Source-Eigenschaft vom Typ string, die den Dateipfad des Bilds angibt. Die Fotoobjekte werden derzeit als Dateipfade angezeigt.

Damit die Fotos als Bilder angezeigt werden, erstellen Sie DataTemplate als Ressource:

<Window.Resources>


...


<!--DataTemplate to display Photos as images
    instead of text strings of Paths-->
<DataTemplate DataType="{x:Type local:Photo}">
  <Border Margin="3">
    <Image Source="{Binding Source}"/>
  </Border>
</DataTemplate>


...


</Window.Resources>

Beachten Sie, dass die DataType-Eigenschaft der TargetType-Eigenschaft von Style stark ähnelt. Wenn sich DataTemplate im Ressourcenabschnitt befindet, wenn Sie die DataType-Eigenschaft auf einen Typ festlegen und ihr nicht x:Key zuweisen, wird DataTemplate jedes Mal angewendet, wenn dieser Typ vorkommt. Sie haben immer die Möglichkeit, DataTemplate mit x:Key zuzuweisen und dann als StaticResource für Eigenschaften festzulegen, die DataTemplate-Typen verwenden, z. B. die ItemTemplate-Eigenschaft oder die ContentTemplate-Eigenschaft.

Durch die DataTemplate im oben genannten Beispiel wird im Wesentlichen definiert, dass bei jedem Vorhandensein eines Photo-Objekts dieses als Image innerhalb von Border angezeigt werden soll. Mit dieser DataTemplate sieht die Anwendung jetzt wie folgt aus:

Fotobild

Das Datenvorlagenmodell bietet weitere Features. Wenn Sie beispielsweise Auflistungsdaten anzeigen, die andere Auflistungen enthalten, und dazu einen HeaderedItemsControl-Typ wie Menu oder TreeView verwenden, ist HierarchicalDataTemplate verfügbar. Eine weitere Funktion für Datenvorlagen ist die DataTemplateSelector, mit der Sie eine DataTemplate auswählen können, die auf der Grundlage benutzerdefinierter Logik verwendet werden soll. Weitere Informationen finden Sie unter Übersicht über Datenvorlagen. Dort werden die verschiedenen Features für Datenvorlagen ausführlicher erläutert.

Steuerelementvorlagen

Dieser Abschnitt enthält folgende Unterabschnitte.

  • Ohne Verwendung von ControlTemplate
  • Was ist eine ControlTemplate?
  • Erstellen einer ControlTemplate
  • IsItemsHost-Eigenschaft
  • ItemsPresenter und ContentPresenter
  • TemplateBinding

Nachdem die Fotos nun als Bilder angezeigt werden, sollen sie horizontal statt vertikal angezeigt werden. Das ListBox soll horizontal dargestellt werden.

Ohne Verwendung von ControlTemplate

Beachten Sie, dass Sie nicht unbedingt ControlTemplate verwenden müssen, um ListBox horizontal anzuzeigen. ListBox verfügt über eine ItemsPanel-Eigenschaft, mit der Sie eine ItemsPanelTemplate festlegen können, also die Vorlage, mit der das Layout der ListBox-Elemente gesteuert wird. Eine Möglichkeit besteht darin, einfach ein ListBox-Format zu erstellen und die ItemsPanel-Eigenschaft festzulegen, wie im folgenden Beispiel gezeigt:

<Style TargetType="ListBox">
  <Setter Property="ItemsPanel">
    <Setter.Value>
      <ItemsPanelTemplate>
        <StackPanel Orientation="Horizontal"
                    VerticalAlignment="Center"
                    HorizontalAlignment="Center"/>
      </ItemsPanelTemplate>
    </Setter.Value>
  </Setter>
</Style>

Dies funktioniert ordnungsgemäß und hat ein horizontales ListBox zur Folge. Wie dieses Beispiel zeigt, haben Sie je nach Szenario auch andere Möglichkeiten, als ControlTemplate zu ersetzen. In diesem Beispiel soll ein horizontales ListBox mit zusätzlichen Eigenschaften erstellt werden, z. B. mit abgerundeten Ecken. Also muss die ControlTemplate von ListBox verwendet werden.

Bevor dies anhand eines Beispiels veranschaulicht wird, muss zunächst das Konzept einer ControlTemplate erläutert werden.

Was ist eine ControlTemplate?

Bei den meisten Steuerelementen wird zwischen Darstellung und Verhalten unterschieden. Als Beispiel eine Schaltfläche: die Darstellung ist der erhabene Bereich, auf den Sie klicken können, und das Verhalten ist das Click-Ereignis, das als Reaktion auf ein Klicken ausgelöst wird.

Es kommt vor, dass ein Steuerelement das gewünschte Verhalten aufweist, nicht aber die gewünschte Darstellung. Wie bereits gezeigt, können Sie Formatsetter verwenden, um Eigenschaftenwerte festzulegen, die sich auf das Aussehen des Steuerelements auswirken. Wenn Sie allerdings die Struktur eines Steuerelements ändern oder Eigenschaftenwerte für die Komponenten festlegen möchten, aus denen sich ein Steuerelement zusammensetzt, müssen Sie eine ControlTemplate verwenden.

In WPF definiert die ControlTemplate eines Steuerelements dessen Darstellung. Sie können die Struktur und die Darstellung eines Steuerelements ändern, indem Sie eine neue ControlTemplate für das Steuerelement definieren. Meistens reicht die dadurch gewonnene Flexibilität aus, sodass keine eigenen benutzerdefinierten Steuerelemente geschrieben werden müssen. Wenn Sie keine eigene ControlTemplate für das Steuerelement definieren, rufen Sie die Standardvorlage für das Systemdesign ab. Diese ist für das Standardaussehen des Button-Steuerelements verantwortlich.

Beachten Sie beim Erstellen einer ControlTemplate für Ihr Steuerelement unbedingt, dass Sie die ControlTemplate komplett ersetzen. Sie können ControlTemplate für Button beispielsweise wie folgt definieren.

Beachten Sie, dass durch das ContentPresenter-Element einfach die Stelle gekennzeichnet wird, an der der Content von Button angezeigt werden soll. Die verschiedenen Teile werden in einem späteren Abschnitt erläutert.

<Style TargetType="Button">
  <!--Set to true to not get any properties from the themes.-->
  <Setter Property="OverridesDefaultStyle" Value="True"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Grid>
          <Ellipse Fill="{TemplateBinding Background}"/>
          <ContentPresenter HorizontalAlignment="Center"
                            VerticalAlignment="Center"/>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Wenn dies zur Anwendung kommt, wird Button als Ellipse angezeigt:

Beispiel für Button-ControlTemplate

Das Aussehen des Button, wenn er den Fokus besitzt oder darauf geklickt wird, gehört zur Standarddarstellung der Schaltfläche, die ersetzt wird. Daher empfiehlt es sich ggf., das Aussehen der Schaltfläche im gedrückten Zustand in die Definition aufzunehmen. Ein vollständiges Beispiel finden Sie unter Beispiel für ein Button-ControlTemplate.

Wenn Sie ControlTemplate erstellen, beginnen Sie am besten mit den Beispiel für ControlTemplate. Wenn für Sie die Bestandteile eines Steuerelements von Interesse sind, sehen Sie sich die Designdatei unter Designs an, oder verwenden Sie die Funktion Show Visual Tree von XAMLPad, einer mit dem Windows Software Development Kit (SDK) installierten Anwendung.

Erstellen einer ControlTemplate

Fahren Sie nun mit dem Beispiel fort, und erstellen Sie eine ControlTemplate, mit der eine horizontale ListBox mit abgerundeten Ecken definiert wird. Um die ControlTemplate eines Steuerelements zu ersetzen, legen Sie die Template-Eigenschaft auf die neue ControlTemplate fest.

<Style TargetType="ListBox">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ListBox">
        <Border CornerRadius="5" Background="{TemplateBinding ListBox.Background}">
          <ScrollViewer HorizontalScrollBarVisibility="Auto">
            <StackPanel Orientation="Horizontal"
                       VerticalAlignment="Center"
                       HorizontalAlignment="Center"
                       IsItemsHost="True"/>
          </ScrollViewer>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Wenn Sie die Template-Eigenschaft auf diese Weise festlegen, entspricht dies dem Festlegen anderer Steuerelementeigenschaften mit Style: Sie verwenden Style als Tool zum Festlegen der Template-Eigenschaft. Eine andere Möglichkeit zum Festlegen von ControlTemplate besteht also darin, die Template-Eigenschaft direkt im Steuerelement festzulegen. Bei dieser Vorgehensweise würden Sie ControlTemplate im Resources-Abschnitt erstellen, für diese x:Key bereitstellen und sie dann als statische Ressource verwenden. Ein Beispiel dafür stellt die Template-Eigenschaft dar.

Wie aus dem Beispiel oben ersichtlich, hat die ControlTemplate-Klasse eine TargetType-Eigenschaft, die mit der TargetType-Eigenschaft der Style-Klasse vergleichbar ist. Beachten Sie allerdings, dass im Gegensatz zu Style und DataTemplate für ControlTemplate-Objekte nicht das Konzept eines impliziten Schlüssels gilt. Anders ausgedrückt, wenn Sie über eine eigenständige ControlTemplate verfügen und die TargetType-Eigenschaft auf einen Typ festgelegt ist, wird die ControlTemplate nicht automatisch auf den betreffenden Typ angewendet. Beachten Sie außerdem, dass die TargetType-Eigenschaft für ControlTemplate erforderlich ist, wenn die Vorlagendefinition ContentPresenter enthält.

Probieren Sie ControlTemplate aus. Ersetzen Sie beispielsweise StackPanel durch WrapPanel, legen Sie die HorizontalScrollBarVisibility-Eigenschaft von ScrollViewer auf Disabled fest, und legen Sie dann die Breite von ListBox auf 300 fest. (Mit WrapPanel werden Elemente nur dann in die nächste Zeile verschoben, wenn in der ersten Zeile kein Platz mehr ist. Wenn Sie die HorizontalScrollBarVisibility-Eigenschaft von ScrollViewer nicht auf Disabled festlegen, ist in der ersten Zeile unbegrenzt Platz, da Sie einen Bildlauf bis zum Ende durchführen können. Als Folge davon werden die Elemente in WrapPanel nicht umbrochen.)

IsItemsHost-Eigenschaft

In diesem Beispiel ist die IsItemsHost-Eigenschaft eine wichtige Eigenschaft, die unbedingt vorhanden sein muss. Mit der IsItemsHost-Eigenschaft wird in der Vorlage von ItemsControl (Steuerelementen wie ListBox, die mit einer Liste von Elementen arbeiten) angegeben, wo die generierten Elemente angezeigt werden sollen. Das Festlegen der Eigenschaft auf true in StackPanel hat zur Folge, dass alle zu ListBox hinzugefügten Elemente in StackPanel eingefügt werden. Beachten Sie, dass diese Eigenschaft nur bei Panel-Typen funktioniert.

ItemsPresenter und ContentPresenter

Wenn Sie allerdings einen Bereich in ControlTemplate angeben und auf diese Weise als IsItemsHost kennzeichnen, kann ItemsPanel vom Benutzer des Steuerelements nur mithilfe von ControlTemplate ersetzt werden. Daher sollten Sie dieses Verfahren nur anwenden, wenn der Bereich ausschließlich mithilfe einer Vorlage ersetzt werden soll. Alternativ können Sie das ItemsPresenter-Element verwenden, um zu kennzeichnen, wo die Elemente angezeigt werden sollen, und anschließend ItemsPanelTemplate angeben, indem Sie die ItemsPanel-Eigenschaft festlegen. Auf der ItemsPanelTemplate-Seite finden Sie ein Beispiel dazu. Ein weiteres Beispiel, in dem ItemsPresenter verwendet wird, finden Sie unter Beispiel für ein TreeView-ControlTemplate.

Wenn Sie eine Vorlage für ContentControl, z. B. Button, erstellen, stellt ContentPresenter das entsprechende Element dar. Auf ähnliche Weise positionieren Sie dieses Element in der ControlTemplate Ihres ContentControl-Typs, um anzugeben, wo der Inhalt angezeigt werden soll. Dies wird im Beispiel des Abschnitts Was ist eine ControlTemplate? veranschaulicht. Weitere Beispiele finden Sie unter Beispiel für ein Label-ControlTemplate und Beispiel für ein ListBoxItem-ControlTemplate.

TemplateBinding

Wichtig im vorherigen Beispiel ist auch, dass der Background-Wert auf {TemplateBinding ListBox.Background} festgelegt ist. Dies weist einfach darauf hin, dass der Background von Border mit dem Background-Wert synchronisiert werden muss, der für ListBox festgelegt ist. Eine TemplateBinding ähnelt einer Binding. Tatsächlich ist TemplateBinding effizienter als Binding, hat aber weniger Funktionen. Die Verwendung von TemplateBinding entspricht der Verwendung von Binding, wobei die Source-Eigenschaft auf RelativeSource.TemplatedParent festgelegt ist.

Verwenden Sie TemplateBinding in ControlTemplate, wenn dem Benutzer des Steuerelements die Kontrolle über die Werte bestimmter Eigenschaften gewährt werden soll. TemplateBinding ist eine Markuperweiterung, die durch die TemplateBindingExtension-Klasse dargestellt wird.

Wie Sie vielleicht schon bemerkt haben, ähneln sich DataTemplate und ControlTemplate dahingehend, dass ihre Inhalte die Visualisierung eines Objekts darstellen. Mit der ControlTemplate-Definition von ListBox sieht die Anwendung nun folgendermaßen aus:

Bildschirmabbildung für Formatierungsbeispiel

Trigger

Style, ControlTemplate und DataTemplate verfügen über eine Triggers-Eigenschaft, die eine Reihe von Triggern enthalten kann. Mit einem Trigger werden Eigenschaften festgelegt oder Aktionen gestartet, z. B. eine Animation beim Ändern eines Eigenschaftenwerts oder beim Auslösen eines Ereignisses.

Dieser Abschnitt enthält folgende Unterabschnitte.

  • Eigenschaftentrigger
  • EventTrigger und Storyboards
  • MultiTrigger, DataTrigger und MultiDataTrigger

Eigenschaftentrigger

Um zu veranschaulichen, wie Sie mit Triggern Eigenschaften festlegen können, werden die einzelnen ListBoxItem teilweise transparent dargestellt, bis sie ausgewählt werden.

Mit dem folgenden Format wird der Opacity-Wert von ListBoxItem auf 0.5 festgelegt. Wenn die IsSelected-Eigenschaft true entspricht, wird Opacity jedoch auf 1.0 festgelegt:

<Style TargetType="ListBoxItem">
  <Setter Property="Opacity" Value="0.5" />
  <Setter Property="MaxHeight" Value="75" />
  <Style.Triggers>
    <Trigger Property="IsSelected" Value="True">
        <Setter Property="Opacity" Value="1.0" />
    </Trigger>


...


  </Style.Triggers>
</Style>

In diesem Beispiel wird Trigger zum Festlegen eines Eigenschaftenwerts verwendet. Beachten Sie, dass die Trigger-Klasse auch über die EnterActions-Eigenschaft und die ExitActions-Eigenschaft verfügt, die einen Trigger in die Lage versetzen, Aktionen auszuführen.

Außerdem wurde die MaxHeight-Eigenschaft von ListBoxItem auf 75 festgelegt. In der folgenden Bildschirmabbildung ist das dritte Element ausgewählt:

Formatierte ListView

EventTrigger und Storyboards

Soeben wurde veranschaulicht, dass ein Trigger Eigenschaftenwerte festlegt oder Aktionen auf der Grundlage des Werts einer Eigenschaft startet. Ein weiterer Triggertyp ist EventTrigger, der auf Basis des Vorkommens eines Ereignisses eine Reihe von Aktionen startet. Die folgenden EventTrigger-Objekte geben beispielsweise an, dass, wenn der Mauszeiger auf ListBoxItem zeigt, die MaxHeight-Eigenschaft für die Dauer von 0.2 Sekunden eine Animation bis zu dem Wert von 90 ausführt. Wird die Maus von dem Element weg bewegt, kehrt die Eigenschaft für einen Zeitraum von 1 Sekunde zum ursprünglichen Wert zurück. Beachten Sie, dass es nicht erforderlich ist, einen To-Wert für die MouseLeave-Animation anzugeben. Das liegt daran, dass die Animation den ursprünglichen Wert nachverfolgen kann.

<EventTrigger RoutedEvent="Mouse.MouseEnter">
  <EventTrigger.Actions>
    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Duration="0:0:0.2"
          Storyboard.TargetProperty="MaxHeight"
          To="90"  />
      </Storyboard>
    </BeginStoryboard>
  </EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
  <EventTrigger.Actions>
    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Duration="0:0:1"
          Storyboard.TargetProperty="MaxHeight"  />
      </Storyboard>
    </BeginStoryboard>
  </EventTrigger.Actions>
</EventTrigger>

Weitere Informationen finden Sie unter Übersicht über Storyboards.

In der folgenden Bildschirmabbildung zeigt die Maus auf das dritte Element:

Bildschirmabbildung für Formatierungsbeispiel

MultiTrigger, DataTrigger und MultiDataTrigger

Neben Trigger und EventTrigger stehen weitere Triggertypen zur Verfügung. Mit MultiTrigger können Sie Eigenschaftenwerte auf der Grundlage mehrerer Bedingungen festlegen. Wenn die Eigenschaft der Bedingung datengebunden ist, verwenden Sie DataTrigger und MultiDataTrigger.

Das vollständige Beispiel aus dieser Übersicht finden Sie unter Einführung zum Beispiel zu Stilen und Vorlagen.

Freigegebene Ressourcen und Designs

Eine typische Windows Presentation Foundation (WPF)-Anwendung kann mehrere Ressourcen für Benutzeroberflächen haben, die in der gesamten Anwendung angewendet werden. Diese Gruppe von Ressourcen kann als Design für die Anwendung betrachtet werden. Windows Presentation Foundation (WPF) unterstützt das Packen von Benutzeroberflächenressourcen als Design. Dazu wird ein Ressourcenwörterbuch verwendet, das als ResourceDictionary-Klasse gekapselt ist.

Windows Presentation Foundation (WPF)-Designs werden mithilfe der Mechanismen für Formate und Vorlagen definiert, die von Windows Presentation Foundation (WPF) zum Anpassen der grafischen Darstellung eines Elements verfügbar gemacht werden.

Windows Presentation Foundation (WPF)-Designressourcen werden in eingebetteten Ressourcenwörterbüchern gespeichert. Diese Ressourcenwörterbücher müssen in einer signierten Assembly eingebettet sein. Sie können entweder in derselben Assembly wie der Code oder in einer parallelen Assembly eingebettet werden. Im Fall von PresentationFramework.dll, der Assembly mit Windows Presentation Foundation (WPF)-Steuerelementen, befinden sich die Designressourcen in einer Reihe paralleler Assemblys.

Das Design ist der letzte Ort, an dem nach dem Format eines Elements gesucht wird. Normalerweise beginnt die Suche, indem die Elementstruktur nach einer geeigneten Ressource durchlaufen wird. Danach wird in der Ressourcenauflistung der Anwendung gesucht und zum Schluss das System abgefragt. Auf diese Weise können Anwendungsentwickler das Format für alle Objekte auf Struktur- oder Anwendungsebene neu definieren, bevor das Design erreicht wird.

Sie können Ressourcenwörterbücher als einzelne Dateien definieren, die Ihnen die Wiederverwendung eines Designs über mehrere Anwendungen hinweg ermöglichen. Darüber hinaus können Sie austauschbare Designs erstellen, indem Sie mehrere Ressourcenwörterbücher definieren, die zwar dieselben Ressourcentypen bereitstellen, aber mit anderen Werten. Wenn Sie Designs für eine Anwendung erstellen, empfiehlt es sich, die Formate oder andere Ressourcen auf Anwendungsebene neu zu definieren.

Wenn Sie eine Reihe von Ressourcen, wie Formate und Vorlagen, anwendungsübergreifend gemeinsam nutzen möchten, können Sie eine XAML-Datei erstellen und ResourceDictionary definieren. Sehen Sie sich beispielsweise folgende Bildschirmabbildung an, die das Beispiel zum Formatieren mit ControlTemplates teilweise veranschaulicht.

Beispiele für Steuerelementvorlagen

Bei den XAML-Dateien im Beispiel wird Ihnen auffallen, dass alle Dateien über das folgende Element verfügen:

<ResourceDictionary.MergedDictionaries>
  <ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>

Die Steuerelemente im Beispiel werden im gleichen Format angezeigt, weil die Datei shared.xaml freigegeben ist. Mit dieser Datei wird ein ResourceDictionary definiert, das eine Reihe von Format- und Pinselressourcen enthält.

Weitere Informationen finden Sie unter Zusammengeführte Ressourcenwörterbücher.

Wenn Sie ein Design für ein benutzerdefiniertes Steuerelement erstellen, sehen Sie sich den Abschnitt zur externen Steuerelementbibliothek unter Übersicht über das Erstellen von Steuerelementen an.

Siehe auch

Aufgaben

Gewusst wie: Suchen von Elementen, die mit einer ControlTemplate generiert wurden

Gewusst wie: Suchen von Elementen, die mit einer DataTemplate generiert wurden

Demo für Fotospeicher

Konzepte

Paket-URIs in Windows Presentation Foundation

Weitere Ressourcen

Designs