Übersicht über das WPF-Grafikrendering

Dieses Thema bietet eine Übersicht über die visuelle WPF-Ebene. Es legt den Schwerpunkt auf die Visual-Klasse für die Renderingunterstützung im WPF-Modell.

Rolle des visuellen Objekts

Die Visual-Klasse ist die grundlegende Abstraktion, von der alle FrameworkElement-Objekte abgeleitet werden. Sie dient auch als Einstiegspunkt zum Schreiben neuer Steuerelemente in WPF und kann in vielerlei Hinsicht als Fensterhandle (HWND) im Win32-Anwendungsmodell betrachtet werden.

Das Visual-Objekt ist ein zentrales WPF-Objekt, dessen primäre Rolle die Unterstützung des Renderings ist. Steuerelemente für die Benutzeroberfläche, wie z. B. Button und TextBox, sind von dieser Visual-Klasse abgeleitet und verwenden sie für die Speicherung ihrer Renderingdaten. Das Visual-Objekt bietet Unterstützung für Folgendes:

  • Ausgabeanzeige: Rendern des persistenten, serialisierten Zeichnungsinhalts eines visuellen Objekts.

  • Transformationen: Ausführen von Transformationen auf einem visuellen Objekt.

  • Clipping: Bereitstellen der Clippingbereichsunterstützung für ein visuelles Objekt.

  • Treffertests: Bestimmen, ob eine Koordinate oder eine Geometrie innerhalb der Grenzen eines visuellen Objekts enthalten ist.

  • Berechnungen des Begrenzungsrahmens: Bestimmen des umschließenden Rechtecks eines visuellen Objekts.

Allerdings bietet das Visual-Objekt keine Unterstützung für Features außerhalb des Renderings, z. B.:

  • Ereignisbehandlung

  • Layout

  • Stile

  • Datenbindung

  • Globalisierung

Visual wird als öffentliche abstrakte Klasse verfügbar gemacht, von der untergeordnete Klassen abgeleitet werden müssen. Die folgende Abbildung zeigt die Hierarchie der visuellen Objekte, die in WPF verfügbar gemacht werden.

Diagram of classes derived from the Visual object

DrawingVisual-Klasse

DrawingVisual ist eine einfache Zeichnungsklasse zum Rendern von Formen, Bildern oder Text. Diese Klasse wird als einfach angesehen, da sie keine Layout- oder Ereignisbehandlung bereitstellt, was die Laufzeitleistung verbessert. Aus diesem Grund eignen sich Zeichnungen für Hintergründe und ClipArt. DrawingVisual kann zum Erstellen eines benutzerdefinierten visuellen Objekts verwendet werden. Weitere Informationen finden Sie unter Verwenden von DrawingVisual-Objekten.

Viewport3DVisual-Klasse

Viewport3DVisual fungiert als Brücke zwischen 2D-Visual- und Visual3D-Objekten. Die Visual3D-Klasse ist die Basisklasse für alle dreidimensionalen visuellen Elemente. Sie müssen für Viewport3DVisual einen Camera-Wert und einen Viewport-Wert definieren. Die Kamera ermöglicht die Anzeige der Szene. Der Anzeigebereich legt fest, wo die Projektion auf der 2D-Fläche zuordnet. Weitere Informationen zu 3D in WPF finden Sie unter Übersicht über 3D-Grafiken.

ContainerVisual-Klasse

Die ContainerVisual-Klasse wird als Container für eine Auflistung von Visual-Objekten verwendet. Die DrawingVisual-Klasse wird von der ContainerVisual-Klasse abgeleitet und ermöglicht die Aufnahme einer Auflistung von visuellen Objekten.

Zeichnungsinhalt in visuellen Objekten

Ein Visual-Objekt speichert seine Renderingdaten als eine Vektorgrafikanweisungsliste. Jedes Element in der Anweisungsliste stellt einen Satz von Grafikdaten einer niedrigeren Ebene und dazugehörige Ressourcen in einem serialisierten Format dar. Es gibt vier verschiedene Typen von Renderingdaten, die Zeichnungsinhalt enthalten können.

Zeichnungsinhaltstyp BESCHREIBUNG
Vektorgrafik Stellt Vektorgrafikdaten und alle zugehörigen Brush- und Pen-Informationen dar.
Image Stellt ein Bild innerhalb eines von Rect definierten Bereichs dar.
Glyphe Stellt eine Zeichnung dar, die einen GlyphRun rendert, wobei es sich um eine Sequenz von Glyphen aus einer angegebenen Schriftartenressource handelt. So wird Text dargestellt.
Video Stellt eine Zeichnung dar, die Video rendert.

Mit dem DrawingContext können Sie ein Visual mit visuellem Inhalt auffüllen. Bei Verwendung der Zeichnen-Befehle eines DrawingContext-Objekts speichern Sie einen Satz von Renderingdaten, die später vom Grafiksystem verwendet werden. Sie zeichnen also nicht in Echtzeit auf dem Bildschirm.

Beim Erstellen eines WPF-Steuerelements, wie z. B. einer Button, generiert das Steuerelement implizit Renderingdaten für die eigene Darstellung. Wenn z. B. die Content-Eigenschaft der Button festgelegt wird, speichert das Steuerelement eine Renderingdarstellung einer Glyphe.

Visual beschreibt den Inhalt als mindestens ein Drawing-Objekt, das in einer DrawingGroup enthalten ist. Eine DrawingGroup beschreibt außerdem Durchlässigkeitsmasken, Transformationen, Bitmapeffekte und andere Vorgänge, die auf ihre Inhalte angewandt werden. DrawingGroup-Vorgänge werden in der folgenden Reihenfolge angewandt, wenn Inhalte gerendert werden: OpacityMask, Opacity, BitmapEffect, ClipGeometry, GuidelineSet und dann Transform.

Die folgende Abbildung zeigt die Reihenfolge, in der DrawingGroup-Vorgänge während der Renderingsequenz angewandt werden.

DrawingGroup order of operations
Reihenfolge der DrawingGroup-Vorgänge

Weitere Informationen finden Sie unter Übersicht über Zeichnungsobjekte.

Zeichnungsinhalt auf Ebene des visuellen Objekts

Instanziieren Sie nie direkt einen DrawingContext. Sie können jedoch einen Zeichnungskontext mit bestimmten Methoden erreichen, z. B. DrawingGroup.Open und DrawingVisual.RenderOpen. Im folgenden Beispiel wird ein DrawingContext aus einem DrawingVisual abgerufen und zum Zeichnen eines Rechtecks verwendet.

// Create a DrawingVisual that contains a rectangle.
private DrawingVisual CreateDrawingVisualRectangle()
{
    DrawingVisual drawingVisual = new DrawingVisual();

    // Retrieve the DrawingContext in order to create new drawing content.
    DrawingContext drawingContext = drawingVisual.RenderOpen();

    // Create a rectangle and draw it in the DrawingContext.
    Rect rect = new Rect(new System.Windows.Point(160, 100), new System.Windows.Size(320, 80));
    drawingContext.DrawRectangle(System.Windows.Media.Brushes.LightBlue, (System.Windows.Media.Pen)null, rect);

    // Persist the drawing content.
    drawingContext.Close();

    return drawingVisual;
}
' Create a DrawingVisual that contains a rectangle.
Private Function CreateDrawingVisualRectangle() As DrawingVisual
    Dim drawingVisual As New DrawingVisual()

    ' Retrieve the DrawingContext in order to create new drawing content.
    Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()

    ' Create a rectangle and draw it in the DrawingContext.
    Dim rect As New Rect(New Point(160, 100), New Size(320, 80))
    drawingContext.DrawRectangle(Brushes.LightBlue, CType(Nothing, Pen), rect)

    ' Persist the drawing content.
    drawingContext.Close()

    Return drawingVisual
End Function

Auflisten des Zeichnungsinhalts auf der Ebene eines visuellen Objekts

Neben ihren anderen Verwendungszwecken bieten Drawing-Objekte auch ein Objektmodell für das Auflisten des Inhalts eines Visual.

Hinweis

Wenn Sie den Inhalt des visuellen Objekts auflisten, rufen Sie Drawing-Objekte und nicht die zugrunde liegende Darstellung der Renderingdaten als Anweisungsliste für Vektorgrafiken ab.

Im folgenden Beispiel wird die GetDrawing-Methode verwendet, um den DrawingGroup-Wert einer Visual-Methode abzurufen und sie aufzuzählen.

public void RetrieveDrawing(Visual v)
{
    DrawingGroup drawingGroup = VisualTreeHelper.GetDrawing(v);
    EnumDrawingGroup(drawingGroup);
}

// Enumerate the drawings in the DrawingGroup.
public void EnumDrawingGroup(DrawingGroup drawingGroup)
{
    DrawingCollection dc = drawingGroup.Children;

    // Enumerate the drawings in the DrawingCollection.
    foreach (Drawing drawing in dc)
    {
        // If the drawing is a DrawingGroup, call the function recursively.
        if (drawing is DrawingGroup group)
        {
            EnumDrawingGroup(group);
        }
        else if (drawing is GeometryDrawing)
        {
            // Perform action based on drawing type.
        }
        else if (drawing is ImageDrawing)
        {
            // Perform action based on drawing type.
        }
        else if (drawing is GlyphRunDrawing)
        {
            // Perform action based on drawing type.
        }
        else if (drawing is VideoDrawing)
        {
            // Perform action based on drawing type.
        }
    }
}

Verwenden von visuellen Objekten zum Erstellen von Steuerelementen

Viele der Objekte in WPF bestehen aus anderen visuellen Objekten, d. h., sie können unterschiedliche Hierarchien von untergeordneten Objekten enthalten. Viele Benutzeroberflächenelemente in WPF, z. B. Steuerelemente, bestehen aus mehreren visuellen Objekten, die unterschiedliche Typen von Renderingelementen darstellen. Das Button-Steuerelement kann beispielsweise eine Reihe anderer Objekte enthalten, einschließlich ClassicBorderDecorator, ContentPresenter und TextBlock.

Der folgende Code zeigt ein im Markup definiertes Button-Steuerelement an.

<Button Click="OnClick">OK</Button>

Sollten Sie die visuellen Objekte auflisten, die das Button-Steuerelement standardmäßig umfassen, finden Sie die unten dargestellte Hierarchie von visuellen Objekten vor:

Diagram of visual tree hierarchy

Das Button-Steuerelement enthält ein ClassicBorderDecorator-Element, in dem wiederum ein ContentPresenter-Element enthalten ist. Das ClassicBorderDecorator-Element ist für das Zeichnen eines Rahmens und eines Hintergrunds für den Button verantwortlich. Das ContentPresenter-Element ist für das Anzeigen des Inhalts der Button verantwortlich. Da Sie Text anzeigen, enthält das ContentPresenter-Element in diesem Fall ein TextBlock-Element. Die Tatsache, dass das Button-Steuerelement einen ContentPresenter verwendet, bedeutet, dass der Inhalt von anderen Elementen dargestellt werden kann, z. B. von einem Image oder einer Geometrie wie EllipseGeometry.

Steuerelementvorlagen

Der Schlüssel zur Erweiterung eines Steuerelements in eine Hierarchie von Steuerelementen ist die ControlTemplate. Eine Steuerelementvorlage gibt die visuelle Standardhierarchie für ein Steuerelement an. Wenn Sie explizit auf ein Steuerelement verweisen, verweisen Sie implizit auf dessen visuelle Hierarchie. Sie können die Standardwerte für eine Steuerelementvorlage überschreiben, um eine angepasste visuelle Darstellung für ein Steuerelement zu erstellen. Sie könnten z. B. den Wert für die Hintergrundfarbe des Button-Steuerelements ändern, sodass sie einen Farbwert eines linearen Farbverlaufs anstelle eines Volltonfarbwerts verwendet. Weitere Informationen finden Sie unter Button-Stile und Vorlagen.

Ein Element der Benutzeroberfläche (z. B. ein Button-Steuerelement) enthält mehrere Anweisungslisten für Vektorgrafiken, die die gesamte Renderingdefinition eines Steuerelements beschreiben. Der folgende Code zeigt ein im Markup definiertes Button-Steuerelement an.

<Button Click="OnClick">
  <Image Source="images\greenlight.jpg"></Image>
</Button>

Sollten Sie die visuellen Objekte und Anweisungslisten für Vektorgrafiken auflisten, die das Button-Steuerelement umfassen, finden Sie die unten dargestellte Hierarchie von Objekten vor:

Diagram of visual tree and rendering data

Das Button-Steuerelement enthält ein ClassicBorderDecorator-Element, in dem wiederum ein ContentPresenter-Element enthalten ist. Das ClassicBorderDecorator-Element ist dafür verantwortlich, alle diskreten Grafikelemente zu zeichnen, aus denen der Rahmen und der Hintergrund einer Schaltfläche bestehen. Das ContentPresenter-Element ist für das Anzeigen des Inhalts der Button verantwortlich. Da Sie ein Bild anzeigen, enthält das ContentPresenter-Element in diesem Fall ein Image-Element.

Es gibt mehrere Dinge im Zusammenhang mit der Hierarchie von visuellen Objekten und Anweisungslisten für Vektorgrafiken zu beachten:

  • Die Reihenfolge in der Hierarchie stellt die Renderingreihenfolge der Zeichnungsinformationen dar. Aus dem visuellen Stammelement werden untergeordnete Elemente von links nach rechts und von oben nach unten durchlaufen. Wenn ein Element über visuelle untergeordnete Elemente verfügt, werden diese vor den gleichgeordneten Elementen des Elements durchlaufen.

  • Elemente in der Hierarchie, die keine Blattknoten sind, wie z. B. ContentPresenter, werden verwendet, um untergeordnete Elemente aufzunehmen. Sie enthalten keine Anweisungslisten.

  • Wenn ein visuelles Element eine Anweisungsliste für Vektorgrafiken und visuelle untergeordnete Elemente enthält, wird die Anweisungsliste im übergeordneten visuellen Element vor Zeichnungen in einem der untergeordneten visuellen Objekte gerendert.

  • Die Elemente in der Anweisungsliste für Vektorgrafiken werden von links nach rechts gerendert.

Visuelle Struktur

Die visuelle Struktur enthält alle visuellen Elemente, die in der Benutzeroberfläche einer Anwendung verwendet werden. Da ein visuelles Element persistent gespeicherte Zeichnungsinformationen enthält, können Sie sich die visuelle Struktur als Szenengraph vorstellen, der alle Renderinginformationen enthält, die erforderlich sind, um die Ausgabe auf dem Anzeigegerät zu erstellen. Diese Struktur ist die Ansammlung aller visuellen Elemente, die direkt von der Anwendung im Code oder im Markup erstellt werden. Die visuelle Struktur enthält auch alle visuellen Elemente, die von der Vorlagenerweiterung der Elemente, wie z.B. Steuerelemente und Datenobjekte, erstellt werden.

Der folgende Code zeigt ein im Markup definiertes StackPanel-Element an.

<StackPanel>
  <Label>User name:</Label>
  <TextBox />
  <Button Click="OnClick">OK</Button>
</StackPanel>

Sollten Sie die visuellen Objekte auflisten, die das StackPanel-Element standardmäßig umfassen, finden Sie die unten dargestellte Hierarchie von visuellen Objekten vor:

Diagram of visual tree hierarchy of a StackPanel control.

Renderingreihenfolge

Die visuelle Struktur bestimmt die Renderingreihenfolge der visuellen WPF- und Zeichnungsobjekte. Die Reihenfolge des Durchlaufs beginnt mit dem visuellen Stammelement, das der oberste Knoten in der visuellen Struktur ist. Die untergeordnete Elemente des visuellen Stammelements werden von links nach rechts durchlaufen. Wenn ein visuelles Objekt über untergeordnete Elemente verfügt, werden seine untergeordneten Elemente vor den gleichgeordneten visuellen Elementen durchlaufen. Dies bedeutet, dass der Inhalt eines untergeordneten visuellen Objekts vor dem Inhalt des visuellen Objekts selbst gerendert wird.

Diagram of the visual tree rendering order

Visuelles Stammobjekt

Das visuelle Stammobjekt ist das oberste Element in der Hierarchie einer visuellen Struktur. In den meisten Clientanwendungen ist die Basisklasse für das visuelle Stammobjekt Window oder NavigationWindow. Wenn Sie jedoch visuelle Objekte in einer Win32-Anwendung hosten, ist das visuelle Stammobjekt das oberste visuelle Objekt, das Sie im Win32-Fenster hosten. Weitere Informationen finden Sie unter Tutorial: Hosten von visuellen Objekten in einer Win32-Anwendung.

Beziehung zur logischen Struktur

Die logische Struktur in WPF stellt die Elemente einer Anwendung zur Laufzeit dar. Obwohl Sie die Struktur nicht direkt bearbeiten, ist diese Ansicht der Anwendung nützlich, um die Vererbung von Eigenschaften und das Ereignisrouting nachzuvollziehen. Im Gegensatz zur visuellen Struktur kann die logische Struktur nicht visuelle Datenobjekte (z. B. ListItem) darstellen. In vielen Fällen ist die logische Struktur eng an die Markupdefinitionen einer Anwendung angelehnt. Der folgende Code zeigt ein im Markup definiertes DockPanel-Element an.

<DockPanel>
  <ListBox>
    <ListBoxItem>Dog</ListBoxItem>
    <ListBoxItem>Cat</ListBoxItem>
    <ListBoxItem>Fish</ListBoxItem>
  </ListBox>
  <Button Click="OnClick">OK</Button>
</DockPanel>

Sollten Sie die logischen Objekte auflisten, die das DockPanel-Element standardmäßig umfassen, finden Sie die unten dargestellte Hierarchie von logischen Objekten vor:

Tree diagram
Diagramm der logischen Struktur

Die visuelle Struktur und die logische Struktur werden mit dem aktuellen Satz von Anwendungselementen synchronisiert und spiegeln dabei alle Hinzufügungen, Löschungen oder Änderungen von Elementen wider. Die Strukturen liefern jedoch verschiedene Ansichten der Anwendung. Im Gegensatz zur visuellen Struktur erweitert die logische Struktur nicht das ContentPresenter-Element eines Steuerelements. Dies bedeutet, dass keine direkte 1:1-Entsprechung zwischen einer logischen Struktur und einer visuellen Struktur für den gleichen Satz von Objekten vorhanden ist. So werden durch Aufruf der GetChildren-Methode des LogicalTreeHelper-Objekts und der GetChild-Methode des VisualTreeHelper-Objekts mit dem gleichen Element als Parameter unterschiedliche Ergebnisse erzielt.

Weitere Informationen zu der logischen Struktur finden Sie unter Strukturen in WPF.

Anzeigen der visuellen Struktur mit XamlPad

Das WPF-Tool XamlPad bietet eine Option zum Anzeigen und Durchsuchen der visuellen Struktur, die dem aktuell definierten XAML-Inhalt entspricht. Klicken Sie auf die Schaltfläche Visuelle Struktur anzeigen der Menüleiste, um die visuelle Struktur anzuzeigen. Im Folgenden wird die Erweiterung des XAML-Inhalts in Knoten in der visuellen Struktur im Panel Visueller Struktur-Explorer in XamlPad veranschaulicht:

Visual Tree Explorer panel in XamlPad

Beachten Sie, dass die Steuerelemente Label, TextBox und Button jeweils eine separate visuelle Objekthierarchie im Panel Visueller Struktur-Explorer von XamlPad anzeigen. Dies ist darauf zurückzuführen, dass WPF-Steuerelemente über eine ControlTemplate verfügen, die die visuelle Struktur dieses Steuerelements enthält. Wenn Sie explizit auf ein Steuerelement verweisen, verweisen Sie implizit auf dessen visuelle Hierarchie.

Erstellung von visuellen Leistungsprofilen

WPF stellt eine Suite von Leistungsprofilerstellungstools bereit, mit deren Hilfe Sie das Laufzeitverhalten der Anwendung analysieren und die Typen der anwendbaren Leistungsoptimierungen bestimmen können. Das Visual Profiler-Tool bietet eine umfassende grafische Sicht der Leistungsdaten, indem diese direkt der visuellen Struktur der Anwendung zugeordnet werden. In diesem Screenshot verschafft Ihnen der Abschnitt CPU-Auslastung von Visual Profiler eine genaue Aufschlüsselung der Nutzung von WPF-Diensten eines Objekts, z. B. Rendering und Layout.

Visual Profiler display output
Visual Profiler-Anzeigeausgabe

Verhalten des visuellen Renderings

WPF verfügt über Funktionen, die das Renderingverhalten visueller Objekte beeinflussen: Retained Mode-Grafiken, Vektorgrafiken und geräteunabhängige Grafiken.

Retained Mode-Grafiken

Einer der Schlüssel zum Verständnis der Rolle des visuellen Objekts ist der Unterschied zwischen Grafiksystemen mit Direktmodus und Retained Mode. Eine standardmäßige Win32-Anwendung, die auf GDI oder GDI+ basiert, verwendet ein Grafiksystem mit unmittelbaren Modus. Das heißt, dass die Anwendung für das Neuzeichnen des Teils des Clientbereichs verantwortlich ist, der aufgrund einer Aktion, z.B. Änderung der Größe eines Fensters, oder eines Objekts, dessen visuelle Darstellung geändert wird, ungültig ist.

Diagram of Win32 rendering sequence

Im Gegensatz dazu verwendet WPF ein Retained Mode-System. Dies bedeutet, dass Objekte, die eine visuelle Darstellung haben, einen Satz serialisierter Zeichnungsdaten definieren. Nachdem die Zeichnungsdaten definiert wurden, ist das System für alle Repaint-Anforderungen zum Rendern der Anwendungsobjekte verantwortlich. Auch zur Laufzeit können Sie Anwendungsobjekte ändern oder erstellen und das System weiterhin auf Zeichnungsanforderungen reagieren lassen. Die Leistungsstärke eines Grafiksystems mit Retained Mode ist darauf zurückzuführen, dass Zeichnungsinformationen stets in einem serialisierten Zustand von der Anwendung gespeichert werden, die Verantwortung für das Rendering aber dem System überlassen wird. Das folgende Diagramm zeigt, wie die Anwendung WPF für die Reaktion auf Zeichnungsanforderungen verwendet.

Diagram of WPF rendering sequence

Intelligentes Neuzeichnen

Einer der größten Vorteile bei der Verwendung von Grafiken mit dem Retained Mode besteht darin, dass WPF effizient optimieren kann, was in der Anwendung neu gezeichnet werden muss. Auch wenn Sie über eine komplexe Szene mit unterschiedlicher Deckkraft verfügen, müssen Sie im Allgemeinen nicht für besondere Zwecke Code zum Neuzeichnen optimieren. Vergleichen Sie dies mit der Win32-Programmierung, bei der Sie viele Ressourcen in die Optimierung Ihrer Anwendung durch Minimierung des Neuzeichnungaufwands im Aktualisierungsbereich investieren können. Ein Beispiel für den Typ der Komplexität in Verbindung mit der Optimierung der Neuzeichnung in Win32-Anwendungen finden Sie unter Neuzeichnen im Aktualisierungsbereich.

Vektorgrafiken

WPF verwendet Vektorgrafiken als Renderingdatenformat. Vektorgrafiken – darunter Scalable Vector Graphics (SVG), Windows-Metadateien (WMF) und TrueType-Schriftarten – speichern Renderingdaten und übertragen sie als Liste von Anweisungen, die beschreiben, wie ein Bild mit Grafikprimitiven neu erstellt wird. TrueType-Schriftarten beispielsweise sind Umrissschriftarten, die einen Satz von Linien, Kurven und Befehlen anstelle eines Arrays von Pixeln beschreiben. Einer der wichtigsten Vorteile von Vektorgrafiken ist die Möglichkeit, auf eine beliebige Größe und Auflösung zu skalieren.

Im Gegensatz zu Vektorgrafiken speichern Bitmapgrafiken Renderingdaten als pixelweise Darstellung eines Bilds, die bereits für eine bestimmte Auflösung gerendert ist. Einer der wichtigsten Unterschiede zwischen Bitmap- und Vektorgrafikformaten ist die Originaltreue in Bezug auf das ursprüngliche Bild. Wenn beispielsweise die Größe eines Quellbilds geändert wird, strecken Bitmapgrafiksysteme das Bild, während Vektorgrafiksysteme das Bild skalieren und dabei die Bildtreue beibehalten.

Die folgende Abbildung zeigt ein Quellbild, dessen Größe um 300 % geändert wurde. Beachten Sie die Verzerrungen, die angezeigt werden, wenn das Quellbild als Bitmap-Grafik gestreckt und nicht als Vektorgrafikbild skaliert wird.

Differences between raster and vector graphics

Das folgende Markup zeigt zwei definierte Path-Elemente an. Das zweite Element verwendet eine ScaleTransform, um die Größe der Zeichnungsanweisungen des ersten Elements um 300 % zu ändern. Beachten Sie, dass die Zeichnungsanweisungen in den Path-Elementen unverändert bleiben.

<Path
  Data="M10,100 C 60,0 100,200 150,100 z"
  Fill="{StaticResource linearGradientBackground}"
  Stroke="Black"
  StrokeThickness="2" />

<Path
  Data="M10,100 C 60,0 100,200 150,100 z"
  Fill="{StaticResource linearGradientBackground}"
  Stroke="Black"
  StrokeThickness="2" >
  <Path.RenderTransform>
    <ScaleTransform ScaleX="3.0" ScaleY="3.0" />
  </Path.RenderTransform>
</Path>

Info zu auflösungs- und geräteunabhängiger Grafik

Zwei Systemfaktoren bestimmen die Größe von Text und Grafiken auf dem Bildschirm: Auflösung und DPI. Die Auflösung beschreibt die Anzahl der Pixel, die auf dem Bildschirm angezeigt werden. Mit höherer Auflösung werden Pixel kleiner und lassen Grafiken und Text kleiner erscheinen. Eine Grafik, die auf einem Monitor mit 1024 x 768 angezeigt wird, erscheint viel kleiner, wenn die Auflösung in 1600 x 1200 geändert wird.

Die andere Systemeinstellung, DPI, beschreibt die Größe eines Bildschirmzolls in Pixeln. Die meisten Windows-Systeme verfügen über den DPI-Wert 96, d. h., ein Bildschirmzoll enthält 96 Pixel. Durch Erhöhen der DPI-Einstellung wird der Bildschirmzoll größer, durch Verringern des DPI-Werts wird der Bildschirmzoll kleiner. Das bedeutet, dass ein Bildschirmzoll nicht die gleiche Größe wie ein realer Zoll hat; auf den meisten System trifft dies wahrscheinlich zu. Wenn Sie den DPI-Wert erhöhen, werden mit DPI kompatible Grafiken und Text größer, da Sie den Bildschirmzoll vergrößert haben. Durch Erhöhen des DPI-Werts kann sich die Lesbarkeit von Text, besonders in hoher Auflösung, verbessern.

Nicht alle Programme sind DPI-kompatibel: Einige verwenden Hardwarepixel als primäre Maßeinheit. Eine Änderung des DPI-Systemwerts hat keine Auswirkungen auf diese Anwendungen. Viele andere Clientanwendungen verwenden Einheiten, die mit DPI kompatibel sind, um Schriftgrade zu beschreiben, aber verwenden Pixel, um alles andere zu beschreiben. Ein zu großer oder zu kleiner DPI-Wert kann zu Layoutproblemen für diese Anwendungen führen, da der Text der Anwendungen mit der DPI-Einstellung skaliert wird, während dies bei den Anwendungen der Benutzeroberfläche nicht der Fall ist. Das Problem wurde für mit WPF entwickelte Anwendungen gelöst.

WPF unterstützt die automatische Skalierung mit geräteunabhängigen Pixeln als primärer Maßeinheit anstelle von Hardwarepixeln. Grafiken und Text skalieren ordnungsgemäß ohne zusätzlichen Eingriff seitens der Entwickler*innen von Anwendungen. Die folgende Abbildung veranschaulicht anhand eines Beispiels, wie WPF-Texte und -Grafiken mit unterschiedlichen DPI-Einstellungen angezeigt werden.

Graphics and text at different DPI settings
Grafiken und Text mit unterschiedlichen DPI-Einstellungen

VisualTreeHelper-Klasse

Die VisualTreeHelper-Klasse ist eine statische Hilfsklasse, die Funktionen der unteren Ebene für die Programmierung auf Ebene der visuellen Objekte bereitstellt, was in ganz bestimmten Szenarien nützlich ist, z. B. beim Entwickeln von leistungsstarken benutzerdefinierten Steuerelementen. In den meisten Fällen bieten die WPF-Frameworkobjekte einer höheren Ebene (z. B. Canvas und TextBlock) mehr Flexibilität und einfache Bedienung.

Treffertests

Die VisualTreeHelper-Klasse bietet Methoden für Treffertests für visuelle Objekte, wenn die standardmäßige Unterstützung für Treffertests nicht Ihren Anforderungen entspricht. Sie können mit den HitTest-Methoden in der VisualTreeHelper-Klasse bestimmen, ob sich ein Geometrie- oder Punktkoordinatenwert im Bereich des gerenderten Inhalts eines bestimmten Objekts befindet, z. B. eines Steuerelements oder eines grafischen Elements. Sie können beispielsweise mit Treffertests bestimmen, ob ein Mausklick innerhalb des umschließenden Rechtecks eines Objekts innerhalb der Geometrie eines Kreises liegt. Außerdem können Sie angeben, dass die standardmäßige Implementierung des Treffertests Ihre eigenen benutzerdefinierten Treffertestberechnungen überschreibt.

Weitere Informationen zu Treffertests finden Sie unter Treffertests in der visuellen Ebene.

Auflisten der visuellen Struktur

Die VisualTreeHelper-Klasse stellt Funktionen zum Auflisten der Elemente einer visuellen Struktur bereit. Rufen Sie zum Abrufen eines übergeordneten Elements die GetParent-Methode auf. Rufen Sie zum Abrufen eines untergeordneten Elements oder eines unmittelbaren Nachfolgerelements eines visuellen Objekts die GetChild-Methode auf. Diese Methode gibt ein untergeordnetes Element Visual des übergeordneten Elements am angegebenen Index zurück.

Im folgenden Beispiel wird veranschaulicht, wie Sie alle Nachfolgerelemente eines visuellen Objekts auflisten. Diese Methode können Sie verwenden, wenn Sie alle Renderinginformationen einer Hierarchie von visuellen Objekten serialisieren möchten.

// Enumerate all the descendants of the visual object.
static public void EnumVisual(Visual myVisual)
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++)
    {
        // Retrieve child visual at specified index value.
        Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);

        // Do processing of the child visual object.

        // Enumerate children of the child visual object.
        EnumVisual(childVisual);
    }
}
' Enumerate all the descendants of the visual object.
Public Shared Sub EnumVisual(ByVal myVisual As Visual)
    For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(myVisual) - 1
        ' Retrieve child visual at specified index value.
        Dim childVisual As Visual = CType(VisualTreeHelper.GetChild(myVisual, i), Visual)

        ' Do processing of the child visual object.

        ' Enumerate children of the child visual object.
        EnumVisual(childVisual)
    Next i
End Sub

In den meisten Fällen ist die logische Struktur eine sinnvollere Darstellung der Elemente in einer WPF-Anwendung. Obwohl Sie die logische Struktur nicht ändern, ist diese Ansicht der Anwendung nützlich, um die Vererbung von Eigenschaften und das Ereignisrouting nachzuvollziehen. Im Gegensatz zur visuellen Struktur kann die logische Struktur nicht visuelle Datenobjekte (z. B. ListItem) darstellen. Weitere Informationen zu der logischen Struktur finden Sie unter Strukturen in WPF.

Die VisualTreeHelper-Klasse bietet Methoden zum Zurückgeben des Begrenzungsrahmens von visuellen Objekten. Sie können den Begrenzungsrahmen eines visuellen Objekts zurückgeben, indem Sie GetContentBounds aufrufen. Sie können den Begrenzungsrahmen aller Nachfolgerelemente eines visuellen Objekts, einschließlich des visuellen Objekts selbst, durch Aufrufen von GetDescendantBounds zurückgeben. Der folgende Code zeigt, wie Sie das umschließende Rechteck des visuellen Objekts und aller Nachfolgerknoten berechnen.

// Return the bounding rectangle of the parent visual object and all of its descendants.
Rect rectBounds = VisualTreeHelper.GetDescendantBounds(parentVisual);
' Return the bounding rectangle of the parent visual object and all of its descendants.
Dim rectBounds As Rect = VisualTreeHelper.GetDescendantBounds(parentVisual)

Weitere Informationen