Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym temacie opisano system układu programu Windows Presentation Foundation (WPF). Zrozumienie, jak i kiedy występują obliczenia układu, jest niezbędne do tworzenia interfejsów użytkownika w WPF.
Ten temat zawiera następujące sekcje:
Ramki ograniczeń elementów
Podczas myślenia o układzie w WPF ważne jest, aby zrozumieć ramkę ograniczającą, która otacza wszystkie elementy. Każdy FrameworkElement używany przez system układu może być uważany za prostokąt, który jest umieszczany w układzie. Klasa LayoutInformation zwraca granice alokacji układu elementu lub miejsca. Rozmiar prostokąta zależy od obliczenia dostępnego miejsca na ekranie, rozmiaru wszelkich ograniczeń, właściwości specyficznych dla układu (takich jak margines i wypełnienie) oraz indywidualnego zachowania elementu nadrzędnego Panel . Przetwarzanie tych danych pozwala systemowi układu obliczyć położenie wszystkich elementów podrzędnych określonego Panel. Należy pamiętać, że właściwości rozmiaru zdefiniowane dla elementu nadrzędnego, takie jak Border, wpływają na jego elementy podrzędne.
Poniższa ilustracja przedstawia prosty układ.
Ten układ można osiągnąć przy użyciu następującego kodu XAML.
<Grid Name="myGrid" Background="LightSteelBlue" Height="150">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Name="txt1" Margin="5" FontSize="16" FontFamily="Verdana" Grid.Column="0" Grid.Row="0">Hello World!</TextBlock>
<Button Click="getLayoutSlot1" Width="125" Height="25" Grid.Column="0" Grid.Row="1">Show Bounding Box</Button>
<TextBlock Name="txt2" Grid.Column="1" Grid.Row="2"/>
</Grid>
Pojedynczy TextBlock element jest hostowany w obiekcie Grid. Chociaż tekst wypełnia tylko lewy górny róg pierwszej kolumny, przydzielone miejsce dla elementu TextBlock jest w rzeczywistości znacznie większe. Ramkę ograniczającą dowolnego FrameworkElement można pobrać przy użyciu metody GetLayoutSlot. Poniższa ilustracja przedstawia pole ograniczenia dla TextBlock elementu.
Jak pokazano na żółtym prostokątie, przydzielone miejsce dla TextBlock elementu jest w rzeczywistości znacznie większe niż się wydaje. W miarę dodawania dodatkowych elementów do Grid, ta alokacja może się zmniejszać lub zwiększać w zależności od typu i rozmiaru dodawanych elementów.
Miejsce układu TextBlock jest przekształcane w Path przez użycie metody GetLayoutSlot. Ta technika może być przydatna do wyświetlania ramki ograniczającej elementu.
private void getLayoutSlot1(object sender, System.Windows.RoutedEventArgs e)
{
RectangleGeometry myRectangleGeometry = new RectangleGeometry();
myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1);
Path myPath = new Path();
myPath.Data = myRectangleGeometry;
myPath.Stroke = Brushes.LightGoldenrodYellow;
myPath.StrokeThickness = 5;
Grid.SetColumn(myPath, 0);
Grid.SetRow(myPath, 0);
myGrid.Children.Add(myPath);
txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString();
}
Private Sub getLayoutSlot1(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim myRectangleGeometry As New RectangleGeometry
myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1)
Dim myPath As New Path
myPath.Data = myRectangleGeometry
myPath.Stroke = Brushes.LightGoldenrodYellow
myPath.StrokeThickness = 5
Grid.SetColumn(myPath, 0)
Grid.SetRow(myPath, 0)
myGrid.Children.Add(myPath)
txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString()
End Sub
System układu
W najprostszej formie układ to system rekursywny, który prowadzi do zmiany rozmiaru, ustawienia i narysowania elementu. W szczególności układ opisuje proces mierzenia i rozmieszczania elementów z kolekcji elementu PanelChildren. Układ jest intensywnym procesem. Im większa kolekcja, tym większa Children liczba obliczeń, które należy wykonać. Złożoność można również wprowadzić na podstawie zachowania układu, które jest zdefiniowane przez element Panel będący właścicielem kolekcji. Stosunkowo proste Panel, takie jak Canvas, może mieć znacznie lepszą wydajność niż bardziej złożone Panel, takie jak Grid.
Za każdym razem, gdy dziecko UIElement zmienia swoją pozycję, może to wyzwolić nowe przeszukiwanie przez system układów. Dlatego ważne jest, aby zrozumieć zdarzenia, które mogą wywołać system układu, ponieważ niepotrzebne wywołanie może prowadzić do niskiej wydajności aplikacji. Poniżej opisano proces, który występuje podczas wywołania systemu układu.
Dziecko UIElement rozpoczyna proces rozmieszczenia, zaczynając od pomiaru jego podstawowych właściwości.
Właściwości określania rozmiaru zdefiniowane na FrameworkElement są oceniane, takie jak Width, Height i Margin.
Panel-specyficzna logika jest stosowana, na przykład Dock kierunek bądź układanie Orientation.
Zawartość jest rozmieszczana po zmierzeniu wszystkich elementów podrzędnych.
Kolekcja Children jest rysowana na ekranie.
Proces jest ponownie wywoływany w przypadku, gdy do kolekcji dodawane są dodatkowe Children, gdy zastosowana jest LayoutTransform, lub gdy wywołana zostanie metoda UpdateLayout.
Ten proces i sposób jego wywoływani są definiowane bardziej szczegółowo w poniższych sekcjach.
Mierzenie i rozmieszczanie dzieci
System układu wykonuje dwa etapy dla każdego członka kolekcji Children: etap pomiaru i etap rozmieszczania. Każde dziecko Panel udostępnia metody MeasureOverride i ArrangeOverride w celu osiągnięcia swojego własnego zachowania układu.
Podczas etapu miary każdy członek kolekcji Children jest oceniany. Proces rozpoczyna się od wywołania Measure metody . Ta metoda jest wywoływana w implementacji elementu nadrzędnego Panel, i nie musi być wywoływana jawnie, aby układ się dokonał.
Najpierw są oceniane właściwości rozmiaru UIElement natywnego, takie jak Clip i Visibility. Spowoduje to wygenerowanie wartości nazwanej constraintSize
, która jest przekazywana do MeasureCore elementu.
Po drugie, właściwości struktury zdefiniowane na FrameworkElement są przetwarzane, co wpływa na wartość constraintSize
. Te właściwości zazwyczaj opisują cechy rozmiaru bazowego UIElement, takie jak jego Height, Width, Margini Style. Każda z tych właściwości może zmienić miejsce niezbędne do wyświetlenia elementu.
MeasureOverride jest następnie wywoływane z parametrem constraintSize
.
Uwaga / Notatka
Istnieje różnica między właściwościami Height i Width oraz ActualHeight i ActualWidth. Na przykład właściwość ActualHeight jest wartością obliczoną na podstawie różnych danych dotyczących wysokości oraz systemu układu. Wartość jest ustawiana przez sam system układu na podstawie rzeczywistego przebiegu renderowania i dlatego może nieznacznie odbiegać od ustawionej wartości właściwości, takich jak Height, które są podstawą zmiany wprowadzanej.
Ponieważ ActualHeight jest to wartość obliczeniowa, należy pamiętać, że może być wiele lub stopniowych zgłoszonych zmian w wyniku różnych operacji wykonywanych przez system układu. System układu może obliczać wymaganą przestrzeń pomiarową dla elementów podrzędnych, ograniczenia przez element nadrzędny itd.
Ostatecznym celem przekazu miary jest określenie elementu podrzędnego DesiredSize, który występuje podczas wywołania funkcji MeasureCore. Wartość DesiredSize jest przechowywana przez Measure do użycia podczas rozmieszczania zawartości.
Etap rozmieszczania rozpoczyna się od wywołania metody Arrange. Podczas etapu rozmieszczania element nadrzędny Panel tworzy prostokąt reprezentujący granice elementu podrzędnego. Ta wartość jest przekazywana do metody przetwarzania ArrangeCore .
Metoda ArrangeCore ocenia DesiredSize dziecka i ocenia wszelkie dodatkowe marginesy, które mogą mieć wpływ na renderowany rozmiar elementu.
ArrangeCore generuje element arrangeSize
, który jest przekazywany do ArrangeOverride metody Panel jako parametru.
ArrangeOverride generuje finalSize
elementu podrzędnego. Na koniec metoda ArrangeCore wykonuje ostateczną ocenę właściwości przesunięcia, takich jak margines i wyrównanie, i umieszcza element podrzędny w przewidzianym dla niego miejscu układu. Dziecko nie musi (a często nie) wypełnia całe przydzielone miejsce. Kontrolka zostanie następnie zwrócona do elementu nadrzędnego Panel , a proces układu zostanie ukończony.
Elementy panelu i niestandardowe zachowania układu
WPF zawiera grupę elementów, które pochodzą z Panel. Te Panel elementy umożliwiają wiele złożonych układów. Na przykład układ stosu można łatwo osiągnąć za pomocą elementu StackPanel, natomiast bardziej złożone i swobodnie przepływające układy są możliwe przy użyciu elementu Canvas.
Poniższa tabela zawiera podsumowanie dostępnych elementów układu Panel .
Nazwa panelu | Opis |
---|---|
Canvas | Definiuje obszar, w którym można jawnie umieścić elementy podrzędne na podstawie współrzędnych w odniesieniu do obszaru Canvas. |
DockPanel | Definiuje obszar, w którym można rozmieścić elementy podrzędne w poziomie lub w pionie względem siebie. |
Grid | Definiuje elastyczny obszar siatki składający się z kolumn i wierszy. |
StackPanel | Rozmieszcza elementy podrzędne w jedną linię, która może być zorientowana w poziomie lub w pionie. |
VirtualizingPanel | Zapewnia strukturę dla elementów Panel, które wirtualizują proces zbierania danych podrzędnych. Jest to abstrakcyjna klasa. |
WrapPanel | Umieszcza elementy podrzędne w pozycji sekwencyjnej od lewej do prawej, przenosząc zawartość do następnego wiersza na krawędzi pola zawierającego. Kolejność następuje sekwencyjnie od góry do dołu lub od prawej do lewej, w zależności od wartości ustawienia Orientation. |
W przypadku aplikacji wymagających takiego układu, który nie jest możliwy do osiągnięcia za pomocą żadnego z wstępnie zdefiniowanych elementów Panel, zachowania układu niestandardowego można osiągnąć, dziedzicząc z Panel, a następnie przesłaniając metody MeasureOverride i ArrangeOverride.
Rozważania dotyczące wydajności układu rozmieszczenia
Układ jest procesem rekursywnym. Każdy element podrzędny w kolekcji Children jest przetwarzany przy każdym wywołaniu systemu układu. W związku z tym należy unikać wyzwalania systemu układu, gdy nie jest to konieczne. Poniższe zagadnienia mogą pomóc w lepszej wydajności.
Należy pamiętać, które zmiany wartości właściwości wymuszą rekursywną aktualizację systemu układu.
Właściwości zależności, których wartości mogą spowodować zainicjowanie systemu układu, są oznaczone flagami publicznymi. AffectsMeasure i AffectsArrange podają przydatne wskazówki dotyczące tego, które zmiany wartości właściwości wymuszą rekursywną aktualizację w systemie układu. Ogólnie rzecz biorąc, każda właściwość, która może mieć wpływ na rozmiar pola ograniczenia elementu, powinna mieć flagę ustawioną AffectsMeasure na true. Aby uzyskać więcej informacji, zobacz Przegląd właściwości zależności.
Jeśli to możliwe, użyj elementu RenderTransform zamiast .LayoutTransform
Może LayoutTransform to być bardzo przydatny sposób wpływania na zawartość interfejsu użytkownika. Jeśli jednak efekt przekształcenia nie musi mieć wpływu na położenie innych elementów, najlepiej użyć RenderTransform elementu zamiast, ponieważ RenderTransform nie wywołuje systemu układu. LayoutTransform stosuje transformację i wymusza aktualizację układu cyklicznego, aby uwzględnić nowe położenie elementu, którego dotyczy problem.
Unikaj niepotrzebnych wywołań do .UpdateLayout
Metoda UpdateLayout wymusza aktualizację układu cyklicznego i często nie jest konieczna. Jeśli nie jesteś przekonany, że wymagana jest pełna aktualizacja, zaufaj systemowi układu, aby wywołał tę metodę za ciebie.
Podczas pracy z dużą Children kolekcją rozważ użycie elementu VirtualizingStackPanel zamiast zwykłego StackPanel.
Wirtualizacja kolekcji podrzędnej powoduje, że VirtualizingStackPanel przechowuje w pamięci tylko te obiekty, które znajdują się obecnie w ViewPort obiektu nadrzędnego. W związku z tym wydajność jest znacznie większa w większości scenariuszy.
Renderowanie subpikselowe i zaokrąglanie układu
System graficzny WPF używa jednostek niezależnych od urządzeń, aby umożliwić rozpoznawanie i niezależność urządzeń. Każdy piksel niezależny od urządzenia jest automatycznie skalowany zgodnie z ustawieniem dpi systemu (kropki na cal). Zapewnia to odpowiednie skalowanie aplikacji WPF dla różnych ustawień dpi oraz sprawia, że aplikacja automatycznie dostosowuje się do dpi.
Jednak ta niezależność dpi może tworzyć nieregularne renderowanie krawędzi z powodu antyaliasingu. Te artefakty, zwykle postrzegane jako rozmyte lub półprzezroczyste krawędzie, mogą wystąpić, gdy lokalizacja krawędzi spadnie w środku piksela urządzenia zamiast między pikselami urządzenia. System układu umożliwia dostosowanie tego układu za pomocą zaokrąglania układu. Zaokrąglanie układu polega na tym, że system układu zaokrągla wszystkie niecałkowite wartości pikseli podczas przetwarzania układu.
Zaokrąglanie układu jest domyślnie wyłączone. Aby włączyć zaokrąglanie układu, ustaw właściwość UseLayoutRounding na true
dowolnej FrameworkElement. Ponieważ jest to właściwość zależności, wartość będzie propagowana do wszystkich dzieci w drzewie wizualnym. Aby włączyć zaokrąglanie układu dla całego interfejsu użytkownika, ustaw wartość UseLayoutRounding na true
w kontenerze głównym. Aby zapoznać się z przykładem, zobacz UseLayoutRounding.
Co dalej?
Zrozumienie, jak elementy są mierzone i rozmieszczane, to pierwszy krok w zrozumieniu układu. Aby uzyskać więcej informacji na temat dostępnych Panel elementów, zobacz Panele — omówienie. Aby lepiej zrozumieć różne właściwości pozycjonowania, które mogą mieć wpływ na układ, zobacz Wyrównanie, Marginesy i Omówienie wypełnienia. Gdy będziesz gotowy, aby wszystko połączyć w niewielką aplikację na pulpit, zobacz Przewodnik: Moja pierwsza aplikacja WPF na pulpit.
Zobacz także
.NET Desktop feedback