Przegląd Renderowanie grafiki WPF

Ten temat zawiera omówienie warstwy wizualnej WPF. Koncentruje się na roli Visual klasy do renderowania obsługi w modelu WPF.

Rola obiektu wizualnego

Klasa Visual jest podstawową abstrakcją, z której pochodzi każdy FrameworkElement obiekt. Służy również jako punkt wejścia do pisania nowych kontrolek w WPF, a na wiele sposobów można traktować jako uchwyt okna (HWND) w modelu aplikacji Win32.

Obiekt Visual jest podstawowym obiektem WPF, którego główną rolą jest zapewnienie obsługi renderowania. Kontrolki interfejsu użytkownika, takie jak Button i TextBox, pochodzą z Visual klasy i używają ich do utrwalania danych renderowania. Obiekt Visual zapewnia obsługę następujących funkcji:

  • Wyświetlanie danych wyjściowych: renderowanie utrwalonej, serializowanej zawartości rysunku wizualizacji.

  • Przekształcenia: wykonywanie przekształceń na wizualizacji.

  • Wycinki: zapewnianie obsługi regionu wycinków dla wizualizacji.

  • Testowanie trafień: określanie, czy współrzędna czy geometria znajduje się w granicach wizualizacji.

  • Obliczenia pól ograniczenia: określanie prostokąta ograniczenia wizualizacji.

Visual Jednak obiekt nie obejmuje obsługi funkcji innych niż renderowanie, takich jak:

  • Obsługa zdarzeń

  • Układ

  • Style

  • Powiązanie danych

  • Globalizacja

Visual jest uwidaczniane jako publiczna klasa abstrakcyjna, z której muszą być pochodne klasy podrzędne. Poniższa ilustracja przedstawia hierarchię obiektów wizualnych uwidocznionych w WPF.

Diagram of classes derived from the Visual object

DrawingVisual, klasa

Jest DrawingVisual to uproszczona klasa rysunku używana do renderowania kształtów, obrazów lub tekstu. Ta klasa jest uważana za lekką, ponieważ nie zapewnia układu ani obsługi zdarzeń, co poprawia wydajność środowiska uruchomieniowego. Z tego powodu rysunki są idealne dla tła i klipartu. Można DrawingVisual go użyć do utworzenia niestandardowego obiektu wizualizacji. Aby uzyskać więcej informacji, zobacz Using DrawingVisual Objects (Używanie obiektów DrawingVisual).

Viewport3DVisual, klasa

Element Viewport3DVisual zapewnia most między obiektami 2D Visual i Visual3D . Klasa Visual3D jest klasą bazową dla wszystkich elementów wizualizacji 3D. Wymagane Viewport3DVisual jest zdefiniowanie Camera wartości i Viewport wartości. Aparat umożliwia wyświetlanie sceny. W okienku widokowym ustanawia się, gdzie projekcja jest mapowana na powierzchnię 2D. Aby uzyskać więcej informacji na temat 3D w WPF, zobacz Omówienie grafiki 3D.

ContainerVisual, klasa

Klasa ContainerVisual jest używana jako kontener dla kolekcji Visual obiektów. Klasa DrawingVisual pochodzi z ContainerVisual klasy, umożliwiając jej zawieranie kolekcji obiektów wizualnych.

Rysowanie zawartości w obiektach wizualnych

Obiekt Visual przechowuje dane renderowania jako listę instrukcji grafiki wektorowej. Każdy element na liście instrukcji reprezentuje niski poziom zestawu danych graficznych i skojarzonych zasobów w formacie serializowanym. Istnieją cztery różne typy danych renderowania, które mogą zawierać zawartość rysunku.

Typ zawartości rysunku opis
Grafika wektorowa Reprezentuje dane grafiki wektorowej oraz wszystkie skojarzone Brush i Pen informacje.
Image Reprezentuje obraz w regionie zdefiniowanym przez element Rect.
Glifów Reprezentuje rysunek renderujący GlyphRunobiekt , który jest sekwencją glifów z określonego zasobu czcionki. W ten sposób tekst jest reprezentowany.
Wideo Reprezentuje rysunek renderujący wideo.

Element DrawingContext umożliwia wypełnienie elementu zawartością wizualną Visual . Gdy używasz DrawingContext poleceń rysowania obiektu, przechowujesz zestaw danych renderowanych, które będą później używane przez system graficzny; nie rysujesz na ekranie w czasie rzeczywistym.

Podczas tworzenia kontrolki WPF, takiej jak Button, kontrolka niejawnie generuje dane renderowania dla samego rysunku. Na przykład ustawienie Content właściwości Button powoduje, że kontrolka przechowuje reprezentację renderowania glif.

Element Visual opisuje jego zawartość jako co najmniej jeden Drawing obiekt zawarty w obiekcie DrawingGroup. Opisano DrawingGroup również maski nieprzezroczystości, przekształcenia, efekty mapy bitowej i inne operacje, które są stosowane do jego zawartości. DrawingGroupoperacje są stosowane w następującej kolejności, gdy zawartość jest renderowana: OpacityMask, , OpacityBitmapEffect, ClipGeometry, GuidelineSeta następnie Transform.

Poniższa ilustracja przedstawia kolejność DrawingGroup stosowania operacji podczas sekwencji renderowania.

DrawingGroup order of operations
Kolejność operacji DrawingGroup

Aby uzyskać więcej informacji, zobacz Omówienie obiektów rysunkowych.

Rysowanie zawartości w warstwie wizualnej

Nigdy nie tworzy się bezpośrednio wystąpienia obiektu DrawingContext; można jednak uzyskać kontekst rysunku z określonych metod, takich jak DrawingGroup.Open i DrawingVisual.RenderOpen. Poniższy przykład pobiera obiekt DrawingContext z obiektu DrawingVisual i używa go do narysowania prostokąta.

// 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

Wyliczanie zawartości rysunku w warstwie wizualnej

Oprócz innych zastosowań Drawing obiekty udostępniają również model obiektów do wyliczania zawartości obiektu Visual.

Uwaga

Podczas wyliczania zawartości wizualizacji pobierasz Drawing obiekty, a nie podstawową reprezentację danych renderowania jako listę instrukcji wektorowych.

W poniższym przykładzie użyto GetDrawing metody , aby pobrać DrawingGroup wartość elementu Visual i wyliczyć ją.

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.
        }
    }
}

Jak obiekty wizualne są używane do kompilowania kontrolek

Wiele obiektów w WPF składa się z innych obiektów wizualnych, co oznacza, że mogą zawierać różne hierarchie obiektów potomnych. Wiele elementów interfejsu użytkownika w WPF, takich jak kontrolki, składa się z wielu obiektów wizualnych reprezentujących różne typy elementów renderowania. Na przykład kontrolka Button może zawierać wiele innych obiektów, w tym ClassicBorderDecorator, ContentPresenteri TextBlock.

Poniższy kod przedstawia kontrolkę zdefiniowaną Button w adiustacji.

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

W przypadku wyliczenia obiektów wizualnych składających się na kontrolkę domyślną Button można znaleźć hierarchię obiektów wizualizacji przedstawionych poniżej:

Diagram of visual tree hierarchy

Kontrolka Button zawiera ClassicBorderDecorator element, który z kolei zawiera ContentPresenter element. Element ClassicBorderDecorator jest odpowiedzialny za rysowanie obramowania i tła elementu Button. Element ContentPresenter jest odpowiedzialny za wyświetlanie zawartości elementu Button. W tym przypadku, ponieważ wyświetlasz tekst, ContentPresenter element zawiera TextBlock element. Fakt, że kontrolka Button używa ContentPresenter środka oznacza, że zawartość może być reprezentowana przez inne elementy, takie jak Image lub geometria, na przykład EllipseGeometry.

Szablony kontrolek

Kluczem do rozszerzenia kontrolki w hierarchii kontrolek jest ControlTemplate. Szablon kontrolki określa domyślną hierarchię wizualizacji dla kontrolki. Jeśli jawnie odwołujesz się do kontrolki, niejawnie odwołujesz się do jej hierarchii wizualnej. Możesz zastąpić wartości domyślne szablonu kontrolki, aby utworzyć dostosowany wygląd wizualizacji dla kontrolki. Można na przykład zmodyfikować wartość koloru tła kontrolki Button tak, aby używała wartości koloru gradientu liniowego zamiast wartości koloru stałego. Aby uzyskać więcej informacji, zobacz Style i szablony przycisków.

Element interfejsu użytkownika, taki jak kontrolka Button , zawiera kilka wektorowych instrukcji graficznych opisujących całą definicję renderowania kontrolki. Poniższy kod przedstawia kontrolkę zdefiniowaną Button w adiustacji.

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

W przypadku wyliczenia obiektów wizualnych i list instrukcji grafiki wektorowej, które składają się na kontrolkę Button , można znaleźć hierarchię obiektów przedstawionych poniżej:

Diagram of visual tree and rendering data

Kontrolka Button zawiera ClassicBorderDecorator element, który z kolei zawiera ContentPresenter element. Element ClassicBorderDecorator jest odpowiedzialny za rysowanie wszystkich dyskretnych elementów graficznych, które tworzą obramowanie i tło przycisku. Element ContentPresenter jest odpowiedzialny za wyświetlanie zawartości elementu Button. W tym przypadku, ponieważ wyświetlasz obraz, ContentPresenter element zawiera Image element.

Istnieje kilka punktów, które należy zwrócić uwagę na hierarchię obiektów wizualnych i list instrukcji grafiki wektorowej:

  • Kolejność w hierarchii reprezentuje kolejność renderowania informacji o rysunku. Z elementu wizualizacji głównej elementy podrzędne są przechodzenie, od lewej do prawej, od góry do dołu. Jeśli element zawiera elementy podrzędne wizualizacji, są one przechodzenie przed elementem równorzędnym elementu.

  • Elementy węzłów innych niż liści w hierarchii, takie jak ContentPresenter, są używane do zawierania elementów podrzędnych — nie zawierają list instrukcji.

  • Jeśli element wizualizacji zawiera zarówno listę instrukcji grafiki wektorowej, jak i elementy podrzędne wizualizacji wizualnej, lista instrukcji w elemecie nadrzędnym wizualizacji jest renderowana przed rysunkami w dowolnych obiektach podrzędnych wizualizacji.

  • Elementy na liście instrukcji grafiki wektorowej są renderowane od lewej do prawej.

Drzewo wizualne

Drzewo wizualizacji zawiera wszystkie elementy wizualne używane w interfejsie użytkownika aplikacji. Ponieważ element wizualizacji zawiera utrwalone informacje o rysunku, można traktować drzewo wizualne jako wykres sceny, zawierający wszystkie informacje renderowania potrzebne do utworzenia danych wyjściowych na urządzeniu wyświetlania. To drzewo jest akumulacją wszystkich elementów wizualnych utworzonych bezpośrednio przez aplikację, zarówno w kodzie, jak i w adiustacji. Drzewo wizualizacji zawiera również wszystkie elementy wizualne utworzone przez rozszerzenie szablonu elementów, takich jak kontrolki i obiekty danych.

Poniższy kod przedstawia StackPanel element zdefiniowany w adiustacji.

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

Jeśli chcesz wyliczyć obiekty wizualizacji składające się na StackPanel element w przykładzie znaczników, można znaleźć hierarchię obiektów wizualizacji przedstawionych poniżej:

Diagram of visual tree hierarchy of a StackPanel control.

Kolejność renderowania

Drzewo wizualizacji określa kolejność renderowania obiektów wizualnych i rysunkowych WPF. Kolejność przechodzenia rozpoczyna się od wizualizacji głównej, która jest najbardziej głównym węzłem w drzewie wizualizacji. Elementy podrzędne wizualizacji głównej są następnie przechodzine od lewej do prawej. Jeśli wizualizacja ma elementy podrzędne, jej elementy podrzędne są przechodzenie przed elementami równorzędnymi wizualizacji. Oznacza to, że zawartość wizualizacji podrzędnej jest renderowana przed własną zawartością wizualizacji.

Diagram of the visual tree rendering order

Wizualizacja główna

Wizualizacja główna jest najbardziej głównym elementem w hierarchii drzewa wizualnego. W większości aplikacji klasa bazowa wizualizacji głównej to Window lub NavigationWindow. Jeśli jednak hostujesz obiekty wizualne w aplikacji Win32, wizualizacja główna będzie najbardziej najbardziej hostowaną wizualizacją w oknie Win32. Aby uzyskać więcej informacji, zobacz Samouczek: hostowanie obiektów wizualnych w aplikacji Win32.

Relacja z drzewem logicznym

Drzewo logiczne w WPF reprezentuje elementy aplikacji w czasie wykonywania. Chociaż nie manipulujesz tym drzewem bezpośrednio, ten widok aplikacji jest przydatny do zrozumienia dziedziczenia właściwości i routingu zdarzeń. W przeciwieństwie do drzewa wizualnego drzewo logiczne może reprezentować obiekty danych innych niż wizualne, takie jak ListItem. W wielu przypadkach drzewo logiczne bardzo uważnie mapuje definicje znaczników aplikacji. Poniższy kod przedstawia DockPanel element zdefiniowany w adiustacji.

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

W przypadku wyliczenia obiektów logicznych składających się na DockPanel element w przykładzie znaczników można znaleźć hierarchię obiektów logicznych zilustrowanych poniżej:

Tree diagram
Diagram drzewa logicznego

Zarówno drzewo wizualne, jak i drzewo logiczne są synchronizowane z bieżącym zestawem elementów aplikacji, odzwierciedlając wszelkie dodatki, usunięcie lub modyfikację elementów. Drzewa przedstawiają jednak różne widoki aplikacji. W przeciwieństwie do drzewa wizualnego drzewo logiczne nie rozwija elementu kontrolki ContentPresenter . Oznacza to, że nie istnieje bezpośrednia korespondencja jeden do jednego między drzewem logicznym a drzewem wizualnym dla tego samego zestawu obiektów. W rzeczywistości wywoływanie metody obiektu LogicalTreeHelper i metody obiektu GetChildrenGetChild VisualTreeHelper przy użyciu tego samego elementu co parametr daje różne wyniki.

Aby uzyskać więcej informacji na temat drzewa logicznego, zobacz Drzewa w WPF.

Wyświetlanie drzewa wizualnego za pomocą XamlPad

Narzędzie WPF, XamlPad, udostępnia opcję wyświetlania i eksplorowania drzewa wizualnego odpowiadającego aktualnie zdefiniowanej zawartości XAML. Kliknij przycisk Pokaż drzewo wizualne na pasku menu, aby wyświetlić drzewo wizualizacji. Poniżej przedstawiono rozszerzenie zawartości XAML do węzłów drzewa wizualnego w panelu Eksplorator drzewa wizualnego XamlPad:

Visual Tree Explorer panel in XamlPad

Zwróć uwagę, że kontrolki Label, TextBoxi Button wyświetlają oddzielną hierarchię obiektów wizualnych w panelu Eksplorator drzewa wizualnego XamlPad. Dzieje się tak, ponieważ kontrolki WPF zawierają ControlTemplate drzewo wizualne tej kontrolki. Jeśli jawnie odwołujesz się do kontrolki, niejawnie odwołujesz się do jej hierarchii wizualnej.

Profilowanie wydajności wizualizacji

WPF udostępnia zestaw narzędzi profilowania wydajności, które umożliwiają analizowanie zachowania aplikacji w czasie wykonywania i określanie typów optymalizacji wydajności, które można zastosować. Narzędzie Visual Profiler udostępnia bogaty, graficzny widok danych wydajności przez mapowanie bezpośrednio do drzewa wizualnego aplikacji. Na tym zrzucie ekranu sekcja Użycie procesora CPU w programie Visual Profiler zawiera dokładny podział użycia usług WPF obiektu, takich jak renderowanie i układ.

Visual Profiler display output
Wyświetlanie danych wyjściowych w programie Visual Profiler

Zachowanie renderowania wizualnego

WPF wprowadza kilka funkcji, które wpływają na zachowanie renderowania obiektów wizualnych: zachowaną grafikę tryb, grafikę wektorową i niezależną od urządzenia grafikę.

Zachowana grafika w trybie

Jednym z kluczy do zrozumienia roli obiektu wizualizacji jest zrozumienie różnicy między trybem bezpośrednim i zachowanych systemów graficznych trybu. Standardowa aplikacja Win32 oparta na GDI lub GDI+ używa systemu grafiki w trybie natychmiastowym. Oznacza to, że aplikacja jest odpowiedzialna za przemalowanie części obszaru klienta, która została unieważniona, ze względu na akcję, taką jak zmiana rozmiaru okna lub zmiana wyglądu wizualizacji obiektu.

Diagram of Win32 rendering sequence

Natomiast WPF używa systemu trybu zachowanego. Oznacza to, że obiekty aplikacji, które mają wygląd wizualny, definiują zestaw serializowanych danych rysunkowych. Po zdefiniowaniu danych rysunku system jest odpowiedzialny za odpowiadanie na wszystkie żądania przemalowania w celu renderowania obiektów aplikacji. Nawet w czasie wykonywania można modyfikować lub tworzyć obiekty aplikacji i nadal polegać na systemie do odpowiadania na żądania malowania. Zasilanie w systemie graficznym w trybie zachowanym polega na tym, że informacje o rysunku są zawsze utrwalane w stanie serializowanym przez aplikację, ale renderowanie odpowiedzialności pozostawionej systemowi. Na poniższym diagramie pokazano, jak aplikacja opiera się na WPF do odpowiadania na żądania malowania.

Diagram of WPF rendering sequence

Inteligentne ponowne rysowanie

Jedną z największych zalet korzystania z grafiki w trybie zachowywania jest to, że WPF może wydajnie zoptymalizować to, co należy ponownie wyrysować w aplikacji. Nawet jeśli masz złożoną scenę o różnych poziomach nieprzezroczystości, zazwyczaj nie trzeba pisać kodu specjalnego przeznaczenia, aby zoptymalizować ponowne rysowanie. Porównaj to z programowaniem Win32, w którym można wydać dużo wysiłku w optymalizacji aplikacji, minimalizując ilość ponownego rysowania w regionie aktualizacji. Zobacz Ponowne rysowanie w regionie aktualizacji, aby zapoznać się z przykładem typu złożoności związanego z optymalizowaniem ponownego rysowania w aplikacjach Win32.

Grafika wektorowa

WPF używa grafiki wektorowej jako formatu danych renderowania. Grafika wektorowa — obejmująca skalowalną grafikę wektorową (SVG), metapliki systemu Windows (.wmf) i czcionki TrueType — przechowuje dane renderowania i przesyła je jako listę instrukcji opisujących sposób odtworzenia obrazu przy użyciu elementów pierwotnych graficznych. Na przykład czcionki TrueType to czcionki konspektu, które opisują zestaw wierszy, krzywych i poleceń, a nie tablicę pikseli. Jedną z kluczowych zalet grafiki wektorowej jest możliwość skalowania do dowolnego rozmiaru i rozdzielczości.

W przeciwieństwie do grafiki wektorowej grafika bitowa przechowuje dane renderowania danych jako reprezentację obrazu w pikselach, wstępnie renderowaną dla określonej rozdzielczości. Jedną z kluczowych różnic między formatami map bitowych i wektorowych jest wierność oryginalnego obrazu źródłowego. Na przykład w przypadku modyfikacji rozmiaru obrazu źródłowego systemy graficzne mapy bitowej rozciągną obraz, podczas gdy systemy grafiki wektorowej skaluje obraz, zachowując wierność obrazu.

Poniższa ilustracja przedstawia obraz źródłowy, którego rozmiar został zmieniony o 300%. Zwróć uwagę na zniekształcenia, które pojawiają się, gdy obraz źródłowy jest rozciągnięty jako obraz graficzny mapy bitowej, a nie skalowany jako obraz grafiki wektorowej.

Differences between raster and vector graphics

Poniższy znacznik przedstawia dwa Path zdefiniowane elementy. Drugi element używa elementu , ScaleTransform aby zmienić rozmiar instrukcji rysowania pierwszego elementu o 300%. Zwróć uwagę, że instrukcje rysowania w elementach Path pozostają niezmienione.

<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>

Informacje o rozdzielczości i niezależnej od urządzenia grafiki

Istnieją dwa czynniki systemowe, które określają rozmiar tekstu i grafiki na ekranie: rozdzielczość i DPI. Rozdzielczość opisuje liczbę pikseli wyświetlanych na ekranie. W miarę jak rozdzielczość staje się większa, piksele są mniejsze, co powoduje, że grafika i tekst będą wyświetlane mniej. Grafika wyświetlana na monitorze ustawionym na 1024 x 768 będzie wyglądać znacznie mniejsza, gdy rozdzielczość zostanie zmieniona na 1600 x 1200.

Inne ustawienie systemowe DPI opisuje rozmiar cala ekranu w pikselach. Większość systemów Windows ma dpi 96, co oznacza, że cal ekranu ma 96 pikseli. Zwiększenie ustawienia DPI sprawia, że ekran jest większy; zmniejszenie dpi sprawia, że ekran jest mniejszy. Oznacza to, że cal ekranu nie jest taki sam jak w rzeczywistym calach; w większości systemów to prawdopodobnie nie jest. W miarę zwiększania rozdzielczości DPI grafika z obsługą dpi i tekst stają się większe, ponieważ zwiększono rozmiar cala ekranu. Zwiększenie rozdzielczości DPI może ułatwić odczytywanie tekstu, szczególnie w przypadku wysokich rozdzielczości.

Nie wszystkie aplikacje są obsługujące dpi: niektóre używają pikseli sprzętowych jako podstawowej jednostki miary; zmiana systemowego dpi nie ma wpływu na te aplikacje. Wiele innych aplikacji używa jednostek obsługujących dpi do opisywania rozmiarów czcionek, ale użyj pikseli, aby opisać wszystko inne. Ustawienie DPI za małe lub zbyt duże może spowodować problemy z układem tych aplikacji, ponieważ tekst aplikacji jest skalowany przy użyciu ustawienia DPI systemu, ale interfejs użytkownika aplikacji nie jest. Ten problem został wyeliminowany w przypadku aplikacji opracowanych przy użyciu platformy WPF.

WPF obsługuje automatyczne skalowanie przy użyciu niezależnego piksela urządzenia jako podstawowej jednostki pomiaru, a nie pikseli sprzętu; poprawne skalowanie grafiki i tekstu bez dodatkowej pracy od dewelopera aplikacji. Na poniższej ilustracji przedstawiono przykład wyświetlania tekstu i grafiki WPF w różnych ustawieniach DPI.

Graphics and text at different DPI settings
Grafika i tekst w różnych ustawieniach DPI

VisualTreeHelper, klasa

Klasa VisualTreeHelper jest statyczną klasą pomocnika, która zapewnia funkcje niskiego poziomu do programowania na poziomie obiektu wizualizacji, co jest przydatne w bardzo konkretnych scenariuszach, takich jak opracowywanie kontrolek niestandardowych o wysokiej wydajności. W większości przypadków obiekty struktury WPF wyższego poziomu, takie jak Canvas i TextBlock, oferują większą elastyczność i łatwość użycia.

Testowanie trafień

Klasa VisualTreeHelper udostępnia metody testowania trafień na obiektach wizualnych, gdy domyślna obsługa testu trafień nie spełnia Twoich potrzeb. Metody w VisualTreeHelper klasie umożliwiają HitTest określenie, czy wartość współrzędnych geometrii lub punktu znajduje się w granicach danego obiektu, na przykład kontrolki lub elementu graficznego. Na przykład można użyć testowania trafień, aby określić, czy kliknięcie myszy w prostokątze ograniczenia obiektu mieści się w geometrii okręgu. Można również zastąpić domyślną implementację testowania trafień w celu wykonania własnych niestandardowych obliczeń testu trafień.

Aby uzyskać więcej informacji na temat testowania trafień, zobacz Testowanie trafień w warstwie wizualnej.

Wyliczanie drzewa wizualnego

Klasa VisualTreeHelper udostępnia funkcje wyliczania elementów członkowskich drzewa wizualnego. Aby pobrać element nadrzędny, wywołaj metodę GetParent . Aby pobrać element podrzędny lub bezpośredni element potomny obiektu wizualizacji, wywołaj metodę GetChild . Ta metoda zwraca element podrzędny Visual elementu nadrzędnego w określonym indeksie.

W poniższym przykładzie pokazano, jak wyliczyć wszystkie elementy potomne obiektu wizualizacji, która jest techniką, której można użyć, jeśli interesuje Cię serializacja wszystkich informacji renderowania hierarchii obiektów wizualizacji.

// 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

W większości przypadków drzewo logiczne jest bardziej przydatną reprezentacją elementów w aplikacji WPF. Chociaż nie modyfikujesz drzewa logicznego bezpośrednio, ten widok aplikacji jest przydatny do zrozumienia dziedziczenia właściwości i routingu zdarzeń. W przeciwieństwie do drzewa wizualnego drzewo logiczne może reprezentować obiekty danych innych niż wizualne, takie jak ListItem. Aby uzyskać więcej informacji na temat drzewa logicznego, zobacz Drzewa w WPF.

Klasa VisualTreeHelper udostępnia metody zwracania prostokąta ograniczenia obiektów wizualnych. Możesz zwrócić prostokąt ograniczenia obiektu wizualizacji, wywołując polecenie GetContentBounds. Można zwrócić prostokąt ograniczenia wszystkich elementów potomnych obiektu wizualizacji, w tym samego obiektu wizualizacji, wywołując metodę GetDescendantBounds. Poniższy kod przedstawia sposób obliczania prostokąta ograniczenia obiektu wizualizacji i wszystkich jego elementów potomnych.

// 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)

Zobacz też