Omówienie renderowania grafiki WPF
Ten temat zawiera omówienie warstwy wizualnej WPF. Koncentruje się on na roli klasy Visual na potrzeby obsługi renderowania w modelu WPF.
Rola obiektu wizualnego
Klasa Visual jest podstawową abstrakcją, z której pochodzi każdy obiekt FrameworkElement. Służy również jako punkt startowy do tworzenia nowych kontrolek w WPF i w wielu aspektach można go porównać do uchwytu 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 klasy Visual 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 wizualnego.
Przekształcenia: wykonywanie przekształceń na wizualu.
Klipowanie: zapewnianie obsługi obszaru klatki dla wizualizacji.
Testowanie trafień: określanie, czy współrzędna lub geometria jest zawarta w granicach elementu wizualnego.
Obliczenia pól ograniczenia: określanie prostokąta ograniczenia wizualizacji.
Jednak obiekt Visual 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.
Klasa DrawingVisual
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 jako tło i do klipartów. Za pomocą DrawingVisual można utworzyć obiekt wizualizacji niestandardowej. Aby uzyskać więcej informacji, zobacz Korzystanie z obiektów DrawingVisual.
Klasa Viewport3DVisual
Viewport3DVisual zapewnia most między Visual i obiektami 2D Visual3D. Klasa Visual3D jest klasą bazową dla wszystkich elementów wizualizacji 3D. Viewport3DVisual wymaga zdefiniowania wartości Camera i wartości Viewport. 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 3D Graphics Overview.
Klasa ContainerVisual
Klasa ContainerVisual jest używana jako kontener dla kolekcji obiektów Visual. Klasa DrawingVisual pochodzi z klasy ContainerVisual, 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 i wszelkie powiązane informacje Brush oraz Pen. |
Obraz | Reprezentuje obraz w regionie zdefiniowanym przez Rect. |
Glif | Reprezentuje rysunek odwzorowujący GlyphRun, który jest sekwencją glifów z określonego zasobu fontu. W ten sposób tekst jest reprezentowany. |
Wideo | Reprezentuje rysunek renderujący wideo. |
DrawingContext umożliwia wypełnienie Visual treścią wizualną. W przypadku używania poleceń rysowania obiektu DrawingContext faktycznie 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 właściwości ContentButton powoduje, że kontrolka przechowuje reprezentację renderowania glifu.
Visual opisuje swoją zawartość jako jeden lub więcej obiektów Drawing zawartych w DrawingGroup. DrawingGroup opisuje również maski nieprzezroczystości, przekształcenia, efekty mapy bitowej i inne operacje, które są stosowane do jego zawartości. DrawingGroup operacje są stosowane w następującej kolejności, gdy zawartość jest renderowana: OpacityMask, Opacity, BitmapEffect, ClipGeometry, GuidelineSet, a następnie Transform.
Na poniższej ilustracji przedstawiono kolejność stosowania operacji DrawingGroup podczas renderowania sekwencji.
Kolejność operacji DrawingGroup
Aby uzyskać więcej informacji, zobacz Przegląd rysowania obiektów.
Rysowanie zawartości w warstwie wizualnej
Nigdy nie tworzysz bezpośrednio instancji DrawingContext; można jednak uzyskać kontekst rysowania z niektórych metod, takich jak DrawingGroup.Open i DrawingVisual.RenderOpen. Poniższy przykład pobiera DrawingContext z DrawingVisual i używa go do rysowania 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ń obiekty Drawing również udostępniają model obiektów do wyliczania zawartości Visual.
Notatka
Podczas wyliczania zawartości wizualizacji pobierasz obiekty Drawing, a nie podstawową reprezentację danych renderowania jako listę instrukcji wektorowych.
W poniższym przykładzie użyto metody GetDrawing, aby pobrać DrawingGroup wartość 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 element sterujący Button zdefiniowany w znacznikach.
<Button Click="OnClick">OK</Button>
W przypadku wyliczenia obiektów wizualnych składających się na domyślną kontrolkę Button można znaleźć hierarchię obiektów wizualizacji przedstawionych poniżej:
Kontrolka Button zawiera element ClassicBorderDecorator, który z kolei zawiera element ContentPresenter. Element ClassicBorderDecorator jest odpowiedzialny za rysowanie obramowania i tła Button. Element ContentPresenter jest odpowiedzialny za wyświetlanie zawartości Button. W tym przypadku, ponieważ wyświetlasz tekst, element ContentPresenter zawiera element TextBlock. Fakt, że kontrolka Button używa ContentPresenter 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 list instrukcji grafiki wektorowej opisujących całą definicję renderowania kontrolki. Poniższy kod przedstawia kontrolkę Button zdefiniowaną w znacznikach.
<Button Click="OnClick">
<Image Source="images\greenlight.jpg"></Image>
</Button>
Gdyby wyliczyć obiekty wizualne i instrukcje grafiki wektorowej składające się na kontrolkę Button, można znaleźć hierarchię obiektów przedstawionych poniżej:
Kontrolka Button zawiera element ClassicBorderDecorator, który z kolei zawiera element ContentPresenter. 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 Button. W tym przypadku, ponieważ wyświetlasz obraz, element ContentPresenter zawiera element Image.
Jest kilka kwestii, na które warto zwrócić uwagę w kontekście hierarchii obiektów wizualnych i list instruktażowych grafiki wektorowej.
Kolejność w hierarchii reprezentuje kolejność renderowania informacji o rysunku. Od głównego elementu wizualnego, elementy podrzędne są przetwarzane od lewej do prawej, od góry do dołu. Jeśli element ma elementy podrzędne wizualne, są one przetwarzane przed elementami równorzędnymi.
Elementy węzłów niebędące liśćmi w hierarchii, takie jak ContentPresenter, służą do zawierania elementów podrzędnych — nie zawierają list instrukcji.
Jeśli element wizualny zawiera zarówno listę instrukcji grafiki wektorowej, jak i elementy podrzędne wizualne, lista instrukcji w elemencie nadrzędnym wizualnym jest renderowana przed rysunkami w dowolnych obiektach podrzędnych.
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 zestawieniem wszystkich elementów wizualnych utworzonych bezpośrednio przez aplikację, zarówno w kodzie, jak i w formacie znaczników. Drzewo wizualizacji zawiera również wszystkie elementy wizualne utworzone przez rozszerzenie szablonu elementów, takich jak kontrolki i obiekty danych.
Poniższy kod przedstawia element StackPanel zdefiniowany w znacznikach.
<StackPanel>
<Label>User name:</Label>
<TextBox />
<Button Click="OnClick">OK</Button>
</StackPanel>
Gdybyś miał wyliczyć obiekty wizualne składające się na element StackPanel w przykładzie znaczników, znajdziesz hierarchię obiektów wizualnych zilustrowanych poniżej.
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ą przechodzone przed elementami równorzędnymi wizualizacji. Oznacza to, że zawartość elementu wizualnego podrzędnego jest renderowana przed własną zawartością elementu wizualnego.
Wizualizacja główna
główny element graficzny jest najwyższym elementem w hierarchii drzewa wizualnego. W większości aplikacji klasa bazowa wizualizacji głównej jest 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 działania. 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 element DockPanel zdefiniowany w znacznikach.
<DockPanel>
<ListBox>
<ListBoxItem>Dog</ListBoxItem>
<ListBoxItem>Cat</ListBoxItem>
<ListBoxItem>Fish</ListBoxItem>
</ListBox>
<Button Click="OnClick">OK</Button>
</DockPanel>
Jeśli wymienisz obiekty logiczne, które składają się na element DockPanel w przykładzie znaczników, zobaczysz hierarchię obiektów logicznych zilustrowaną poniżej.
diagram drzewa
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 sterującego 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 GetChildren obiektu LogicalTreeHelper oraz metody VisualTreeHelper obiektu GetChild przy użyciu tego samego elementu co parametr daje różne wyniki.
Aby uzyskać więcej informacji na temat drzewa logicznego, sprawdź sekcję 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 wizualne. Poniżej przedstawiono rozwinięcie zawartości XAML do węzłów drzewa wizualnego w panelu Visual Tree Explorer programu XamlPad.
XamlPad
Zwróć uwagę, że kontrolki Label, TextBoxi Button wyświetlają oddzielną hierarchię obiektów wizualnych w eksploratorze drzewa wizualnego panelu XamlPad. Dzieje się tak, ponieważ kontrolki WPF mają ControlTemplate, które zawiera drzewo wizualne tej kontrolki. Jeśli jawnie odwołujesz się do kontrolki, niejawnie odwołujesz się do jej hierarchii wizualnej.
Profilowanie wydajności wizualnej
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.
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: grafikę trybu zachowanego, grafikę wektorową i niezależną od urządzenia grafikę.
Grafika w trybie zachowanym
Jednym z kluczy do zrozumienia roli obiektu wizualizacji jest zrozumienie różnicy między trybem bezpośrednim a trybem zretencjonowanym w systemach graficznych. 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
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 podczas działania można modyfikować lub tworzyć obiekty aplikacji i nadal polegać na systemie, aby odpowiadać na żądania związane z rysowaniem. Siła systemu graficznego w trybie zachowanym polega na tym, że informacje o rysunku są zawsze zapisywane w postaci serializowanej przez aplikację, ale odpowiedzialność za renderowanie pozostaje w gestii systemu. Na poniższym diagramie pokazano, jak aplikacja opiera się na WPF do odpowiadania na żądania malowania.
diagram
Inteligentne ponowne rysowanie
Jedną z największych zalet korzystania z grafiki w trybie zachowanym jest to, że WPF może efektywnie zoptymalizować, co należy ponownie narysować 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 optymalizacją 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 konturowe, które opisują zestaw linii, 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 jako pikselową reprezentację obrazu, 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 grafiki rastrowej rozciągają obraz, podczas gdy systemy grafiki wektorowej skalują 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.
Poniższy znacznik pokazuje dwa elementy Path zdefiniowane. Drugi element używa 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>
Na temat rozdzielczości i grafiki Device-Independent
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 cal w świecie rzeczywistym; w większości systemów prawdopodobnie tak nie jest. W miarę zwiększania rozdzielczości DPI, grafika dostosowana do DPI i tekst stają się większe, ponieważ zwiększasz 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. Zbyt małe lub zbyt duże ustawienie DPI 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.
Grafika i tekst w różnych ustawieniach DPI
Klasa VisualTreeHelper
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 testów trafień nie spełnia Twoich potrzeb. Można użyć metod HitTest w klasie VisualTreeHelper, aby określić, czy wartość geometrii lub współrzędnych punktu znajduje się w granicach danego obiektu, na przykład kontrolki lub elementu graficznego. Na przykład możesz użyć testowania trafień, aby określić, czy kliknięcie myszy w prostokącie ograniczenia obiektu mieści się w geometrii okręgu. Możesz również zastąpić domyślną implementację testowania trafień, aby wykonać własne niestandardowe obliczenia testu trafień.
Aby uzyskać więcej informacji na temat testowania trafień, zobacz hit testing in the Visual Layer.
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średniego potomka obiektu wizualnego, wywołaj metodę GetChild. Ta metoda zwraca element podrzędny Visual elementu nadrzędnego pod określonym indeksem.
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 Trees in WPF.
Klasa VisualTreeHelper udostępnia metody zwracające prostokąt ograniczający obiektów wizualnych. Można zwrócić prostokąt ograniczenia obiektu wizualizacji, wywołując GetContentBounds. Można zwrócić prostokąt obrysowy wszystkich potomków obiektu wizualnego, wraz z nim samym, wywołując GetDescendantBounds. Poniższy kod przedstawia sposób obliczania prostokąta obwiedni obiektu wizualnego 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ż
- Visual
- VisualTreeHelper
- DrawingVisual
- grafika 2D i obrazowanie
- testowanie trafień w warstwy wizualnej
- Użycie obiektów DrawingVisual
- samouczek : hostowanie obiektów wizualnych w aplikacji Win32
- Optymalizacja wydajności aplikacji WPF
.NET Desktop feedback