Freigeben über


Übersicht über benutzerdefinierte XAML-Panels

Ein -Panel ist ein Objekt, das ein Layoutverhalten für untergeordnete Elemente bereitstellt, die es enthält, wenn das XAML-Layoutsystem (Extensible Application Markup Language) ausgeführt wird und die UI Ihrer App gerendert wird.

Wichtige APIs: Panel, ArrangeOverride, MeasureOverride

Sie können benutzerdefinierte Panels für das XAML-Layout definieren, indem Sie eine benutzerdefinierte Klasse aus der klasse Panel ableiten. Sie stellen das Verhalten für Ihr Panel bereit, indem Sie die MeasureOverride und ArrangeOverrideüberschreiben und Logik bereitstellen, die die untergeordneten Elemente misst und anordnet.

Die Basisklasse des Panels

Um eine benutzerdefinierte Panelklasse zu definieren, können Sie entweder direkt von der Panel Klasse abgeleitet oder von einer der praktischen Panelklassen abgeleitet werden, die nicht versiegelt sind, z. B. Grid oder StackPanel-. Es ist einfacher, von Panelabzuleiten, da es schwierig sein kann, die vorhandene Layoutlogik eines Panels zu umgehen, das bereits ein Layoutverhalten aufweist. Darüber hinaus verfügt ein Panel mit bestimmten Verhaltensweisen möglicherweise über vorhandene Eigenschaften, die für die Layoutmerkmale Ihres Panels nicht relevant sind.

Ihr benutzerdefiniertes Panel erbt von Paneldiese APIs:

  • Die Eigenschaft Kinder.
  • Die Eigenschaften Background, ChildrenTransitions und IsItemsHost sowie die Bezeichner der Abhängigkeitseigenschaften. Keine dieser Eigenschaften ist virtuell, sodass Sie sie in der Regel nicht außer Kraft setzen oder ersetzen. Normalerweise benötigen Sie diese Eigenschaften nicht für benutzerdefinierte Panelszenarien, nicht einmal zum Lesen von Werten.
  • Die Layoutüberschreibungsmethoden MeasureOverride und ArrangeOverride. Diese wurden ursprünglich durch FrameworkElementdefiniert. Die Basis-Panel- Klasse überschreibt diese nicht. Praktische Panels wie Grid verfügen jedoch über Außerkraftsetzungsimplementierungen, die als systemeigener Code implementiert und vom System ausgeführt werden. Die Bereitstellung neuer (oder additiver) Implementierungen für ArrangeOverride und MeasureOverride ist der Großteil des Aufwands, den Sie zum Definieren eines benutzerdefinierten Panels benötigen.
  • Alle anderen APIs von FrameworkElement, UIElement und DependencyObject, wie z. B. Höhe, Sichtbarkeit und so weiter. Sie verweisen manchmal auf Werte dieser Eigenschaften in Ihren Layoutüberschreibungen, aber da sie nicht virtuell sind, setzen Sie sie in der Regel nicht außer Kraft oder ersetzen sie.

Dieser Fokus liegt hier auf der Beschreibung von XAML-Layoutkonzepten, sodass Sie alle Möglichkeiten berücksichtigen können, wie ein benutzerdefiniertes Panel sich im Layout verhalten kann und verhalten sollte. Wenn Sie direkt loslegen und ein Beispiel für die Implementierung eines benutzerdefinierten Panels sehen möchten, schauen Sie sich BoxPanel an, ein Beispiel für die Implementierung eines benutzerdefinierten Panels.

Die Eigenschaft Children

Die Eigenschaft Children ist für ein benutzerdefiniertes Panel relevant, da alle von Panel abgeleiteten Klassen die Eigenschaft Children dafür nutzen, um ihre enthaltenen untergeordneten Elemente in einer Sammlung zu speichern. Children wird als XAML-Inhaltseigenschaft für die Klasse Panel festgelegt, und alle von Panel abgeleiteten Klassen können das Verhalten der XAML-Inhaltseigenschaft erben. Wenn eine Eigenschaft als XAML-Content-Eigenschaft definiert ist, bedeutet dies, dass das XAML-Markup ein Eigenschaftselement weglassen kann, wenn diese Eigenschaft im Markup angegeben wird, und die Werte als direkte Markup-Kinder ("Inhalt") festgelegt werden. Wenn Sie beispielsweise eine Klasse mit dem Namen CustomPanel von Panel- ableiten, die kein neues Verhalten definiert, können Sie dieses Markup weiterhin verwenden:

<local:CustomPanel>
  <Button Name="button1"/>
  <Button Name="button2"/>
</local:CustomPanel>

Wenn ein XAML-Parser dieses Markup liest, ist Children- als XAML-Inhaltseigenschaft für alle von Panel- abgeleiteten Typen bekannt, sodass der Parser die beiden Button--Elemente zur UIElementCollection des Children-Eigenschaftswerts hinzufügt. Die XAML-Inhaltseigenschaft erleichtert eine optimierte Beziehung zwischen übergeordneten und untergeordneten Elementen im XAML-Markup für eine UI-Definition. Weitere Informationen zu XAML-Inhaltseigenschaften und zur Befüllung von Sammlungseigenschaften beim Analysieren von XAML finden Sie im XAML-Syntaxhandbuch.

Der Sammlungstyp, der den Wert der Eigenschaft Children beibehält, ist die Klasse UIElementCollection. UIElementCollection- ist eine stark typierte Auflistung, die UIElement- als erzwungenen Elementtyp verwendet. UIElement- ist ein Basistyp, der von Hunderten praktischen UI-Elementtypen geerbt wird, sodass die Typüberprüfung hier absichtlich locker ist. Es erzwingt, dass Sie keine Brush als direktes untergeordnetes Element eines Panelshaben könnten, und es bedeutet im Allgemeinen, dass nur Elemente, die in der Benutzeroberfläche sichtbar sind und am Layout teilnehmen, als untergeordnete Elemente in einem Panelvorkommen.

In der Regel akzeptiert ein benutzerdefiniertes Panel jedes UIElement-element untergeordnete Element anhand einer XAML-Definition, indem einfach die Merkmale der Children-Eigenschaft as-isverwendet werden. Als erweitertes Szenario können Sie die weitere Typüberprüfung von Kindelementen unterstützen, wenn Sie in Ihren Layout-Overrides durch die Sammlung iterieren.

Neben einer Schleife durch die Children Collection in den Außerkraftsetzungen kann ihre Panellogik auch von Children.Countbeeinflusst werden. Möglicherweise verwenden Sie eine Logik, die den Platz zumindest teilweise basierend auf der Anzahl der Elemente zuweist, anstatt die gewünschten Größen und andere Merkmale der einzelnen Elemente zu berücksichtigen.

Überschreiben der Layoutmethoden

Das grundlegende Modell für die Methoden zur Layoutüberschreibung (MeasureOverride und ArrangeOverride) besteht darin, dass sie über alle untergeordneten Elemente iterieren und die spezifische Methode jedes Unterelements aufrufen sollten. Der erste Layoutzyklus beginnt, wenn das XAML-Layoutsystem die visuelle Darstellung für das Stammfenster festlegt. Da jedes übergeordnete Element das Layout für seine Kind-Elemente aufruft, wird dadurch ein Aufruf an Layoutmethoden an jedes verfügbare UI-Element weitergegeben, das Bestandteil eines Layouts ist. Im XAML-Layout gibt es zwei Phasen: Messen und anordnen.

Sie erhalten kein integriertes Layoutmethodenverhalten für MeasureOverride und ArrangeOverride aus der Basisklasse Panel. Elemente in Kinderelemente werden nicht automatisch als Teil der visuellen XAML-Struktur gerendert. Es liegt an Ihnen, die Elemente dem Layoutprozess bekannt zu machen, indem Sie Layoutmethoden für jedes der Elemente aufrufen, die Sie in untergeordneten Elementen finden, über einen Layoutdurchlauf innerhalb Ihrer MeasureOverride und ArrangeOverride Implementierungen.

Es gibt keinen Grund, Basisimplementierungen in Layoutüberschreibungen aufzurufen, es sei denn, Sie haben ihre eigene Vererbung. Die nativen Methoden für das Layoutverhalten (sofern vorhanden) werden in jedem Fall ausgeführt, und das Nichtaufrufen der Basisimplementierung in Überschreibungen verhindert nicht das Auftreten des nativen Verhaltens.

Während des Messdurchlaufs fragt die Layoutlogik jedes untergeordnete Element nach seiner gewünschten Größe ab, indem die Measure-Methode für dieses untergeordnete Element aufgerufen wird. Durch Aufrufen der Measure-Methode wird der Wert für die eigenschaft DesiredSize festgelegt. Der MeasureOverride Rückgabewert ist die gewünschte Größe für das Panel selbst.

Während des Anordnungsdurchlaufs werden die Positionen und Größen untergeordneter Elemente im x-y-Raum bestimmt, und die Layoutkomposition wird für das Rendern vorbereitet. Ihr Code muss für jedes untergeordnete Element in Children die Methode Arrange aufrufen, damit das Layoutsystem erkennt, dass das Element zum Layout gehört. Der Aufruf Anordnen ist ein Vorläufer für das Layout und Rendering; er informiert das Layoutsystem darüber, wo sich dieses Element befindet, wenn die Komposition zum Rendern übermittelt wird.

Viele Eigenschaften und Werte tragen dazu bei, wie die Layoutlogik zur Laufzeit funktioniert. Eine Möglichkeit, über den Layoutprozess nachzudenken, besteht darin, dass die Elemente ohne untergeordnete Elemente, also im Allgemeinen die am tiefsten geschachtelten Elemente in der Benutzeroberfläche, diejenigen sind, die zuerst Messungen abschließen können. Sie haben keine Abhängigkeiten von untergeordneten Elementen, die ihre gewünschte Größe beeinflussen. Sie haben möglicherweise ihre eigenen bevorzugten Größen, und das sind Größenvorschläge, bis das Layout tatsächlich umgesetzt wird. Dann setzt sich der Messdurchlauf durch den visuellen Baum fort, bis das Wurzelelement seine Maße hat und alle Messungen abgeschlossen werden können.

Das Layoutentwurf muss in das aktuelle App-Fenster passen, sonst werden Teile der Benutzeroberfläche abgeschnitten. Panels sind häufig der Ort, an dem die Abschneidelogik bestimmt wird. Panellogik kann bestimmen, welche Größe innerhalb der MeasureOverride Implementierung verfügbar ist, und möglicherweise die Größenbeschränkungen auf die untergeordneten Elemente anwenden sowie den Platz zwischen diesen untergeordneten Elementen teilen müssen, damit alles so gut wie möglich passt. Das Ergebnis des Layouts ist idealerweise etwas, das verschiedene Eigenschaften aller Teile des Layouts verwendet, aber dennoch in das App-Fenster passt. Dies erfordert sowohl eine gute Implementierung für die Layoutlogik der Panels als auch ein durchdachtes Benutzeroberflächendesign seitens des App-Codes, der eine Benutzeroberfläche mithilfe dieses Panels erstellt. Kein Paneldesign sieht gut aus, wenn das allgemeine UI-Design mehr untergeordnete Elemente enthält, als in die App passen können.

Ein wesentlicher Aspekt, der das Funktionieren des Layoutsystems ermöglicht, besteht darin, dass jedes Element, das auf dem FrameworkElement- basiert, bereits über ein eigenes inhärentes Verhalten verfügt, wenn es als Kind in einem Container fungiert. Beispielsweise gibt es mehrere APIs des FrameworkElements, die entweder das Layoutverhalten beeinflussen oder notwendig sind, damit das Layout überhaupt funktioniert. Dazu gehören:

MeasureOverride

Die MeasureOverride--Methode hat einen Rückgabewert, der vom Layoutsystem als Ausgangs-DesiredSize- für das Panel selbst verwendet wird, wenn die Measure--Methode vom übergeordneten Element im Layout für das Panel aufgerufen wird. Die logischen Auswahlmöglichkeiten innerhalb der Methode sind genauso wichtig wie das, was sie zurückgibt, und die Logik beeinflusst oft, welcher Wert zurückgegeben wird.

Alle Implementierungen von MeasureOverride sollten durch die Childreniterieren und die Measure--Methode für jedes untergeordnete Element aufrufen. Durch Aufrufen der Measure-Methode wird der Wert für die eigenschaft DesiredSize festgelegt. Dies könnte Aufschluss darüber geben, wie viel Platz das Panel selbst benötigt und wie dieser Platz auf die Elemente verteilt oder für ein bestimmtes untergeordnetes Element dimensioniert wird.

Hier ist ein sehr einfaches Skelett einer --MeasureOverride---Methode:

protected override Size MeasureOverride(Size availableSize)
{
    Size returnSize; //TODO might return availableSize, might do something else
     
    //loop through each Child, call Measure on each
    foreach (UIElement child in Children)
    {
        child.Measure(new Size()); // TODO determine how much space the panel allots for this child, that's what you pass to Measure
        Size childDesiredSize = child.DesiredSize; //TODO determine how the returned Size is influenced by each child's DesiredSize
        //TODO, logic if passed-in Size and net DesiredSize are different, does that matter?
    }
    return returnSize;
}

Elemente haben oft eine natürliche Größe, wenn sie für das Layout bereit sind. Nach dem Messdurchlauf gibt die DesiredSize- möglicherweise an, dass die natürliche Größe, wenn die availableSize, die Sie für Measure übergeben haben, kleiner war. Wenn die natürliche Größe größer als die verfügbare Größe (availableSize) ist, die Sie für Measureübergeben haben, wird die gewünschte Größe (DesiredSize) auf die verfügbare Größe (availableSize) beschränkt. So verhält sich die interne Implementierung von Measure, und Ihre Layoutüberschreibungen sollten dieses Verhalten berücksichtigen.

Einige Elemente haben keine natürliche Größe, da sie Auto--Werte für Höhe und Breitehaben. Diese Elemente nutzen die vollständige availableSize, da dies einen Auto--Wert darstellt: die Größe des Elements auf die maximale verfügbare Größe einstellen, welche das unmittelbar übergeordnete Layout kommuniziert, indem Measure mit availableSizeaufgerufen wird. In der Praxis gibt es immer eine Maßeinheit, auf die eine Benutzeroberfläche angepasst wird (auch wenn dies das Fenster der obersten Ebene ist.) Schließlich löst der Messdurchlauf alle Auto--Werte in übergeordnete Einschränkungen auf, und alle Auto Wertelemente erhalten reale Maße (die Sie abrufen können, indem Sie ActualWidth- und ActualHeight-, nach Abschluss des Layouts) überprüfen.

Es ist zulässig, eine Größe an Measure zu übergeben, die mindestens eine unendliche Dimension aufweist, um anzugeben, dass das Panel versuchen kann, seine Größe den Maßen seines Inhalts anzupassen. Jedes gemessene untergeordnete Element legt seinen DesiredSize-Wert unter Verwendung seiner natürlichen Größe fest. Dann wird das Panel während des Arrange-Durchlaufs typischerweise mit dieser Größe angeordnet.

Textelemente wie TextBlock haben eine berechnete ActualWidth und ActualHeight basierend auf ihrer Textzeichenfolge und Texteigenschaften, auch wenn kein Height oder Width Wert festgelegt ist, und diese Dimensionen sollten von der Panellogik berücksichtigt werden. Das Beschneiden von Text ist ein besonders schlechtes Benutzererlebnis.

Auch wenn Ihre Implementierung nicht die gewünschten Größenmessungen verwendet, ist es am besten, die Measure Methode für jedes untergeordnete Element aufzurufen, da dadurch interne und systeminterne Verhaltensweisen ausgelöst werden, die durch das Aufrufen von Measure aktiviert werden. Damit ein Element am Layout teilnehmen kann, muss auf jedes untergeordnete Element während des Messdurchlaufs Measure aufgerufen werden, und während des Anordnungsdurchlaufs muss die Arrange-Methode aufgerufen werden. Durch Aufrufen dieser Methoden werden interne Flags für das Objekt festgelegt und Werte (z. B. die DesiredSize-Eigenschaft) aufgefüllt, die die Layoutlogik des Systems benötigt, wenn die visuelle Struktur erstellt und die Benutzeroberfläche gerendert wird.

Der MeasureOverride Rückgabewert basiert auf der Logik des Panels, die die DesiredSize interpretiert oder andere Größenüberlegungen für jedes untergeordnete Element in Untergeordnete Elemente, wenn Measure- aufgerufen wird. Was Sie mit DesiredSize--Werten von untergeordneten Elementen machen sollen und wie der Rückgabewert von MeasureOverride- sie verwenden sollte, liegt in der Interpretation Ihrer eigenen Logik. Normalerweise fügen Sie die Werte nicht ohne Änderung hinzu, da die Eingabe von MeasureOverride häufig eine feste verfügbare Größe ist, die vom übergeordneten Element des Panels vorgeschlagen wird. Wenn Sie diese Größe überschreiten, wird das Panel selbst möglicherweise abgeschnitten. Normalerweise vergleichen Sie die Gesamtgröße der untergeordneten Elemente mit der verfügbaren Größe des Panels und nehmen bei Bedarf Anpassungen vor.

Tipps und Anleitungen

  • Idealerweise sollte ein benutzerdefiniertes Panel dazu geeignet sein, das erste echte visuelle Element in einer UI-Komposition darzustellen, vielleicht auf einer Ebene direkt unter Page, UserControl oder einem anderen Element, das der Stamm der XAML-Seite ist. Geben Sie in MeasureOverride Implementierungen nicht routinemäßig die Eingabe Größe zurück, ohne die Werte zu prüfen. Wenn die Rückgabe Size einen Infinity Wert enthält, kann dies Ausnahmen in der Laufzeitlayoutlogik auslösen. Ein Infinity Wert kann aus dem Hauptfenster der App stammen, das scrollbar ist und daher keine maximale Höhe aufweist. Andere scrollbare Inhalte könnten dasselbe Verhalten aufweisen.
  • Ein weiterer häufiger Fehler bei MeasureOverride Implementierungen besteht darin, eine neue Standardgröße () zurückzugeben, wobei die Werte für Höhe und Breite 0 sind. Möglicherweise beginnen Sie mit diesem Wert, und es ist sogar der richtige Wert, wenn Ihr Gremium feststellt, dass keiner der untergeordneten Elemente gerendert werden soll. Jedoch führt eine standardmäßige Größe dazu, dass Ihr Panel nicht korrekt durch seinen Host dimensioniert wird. Benötigt keinen Speicherplatz auf der Benutzeroberfläche, erhält daher keinen und wird nicht gerendert. Der gesamte Panelcode funktioniert andernfalls möglicherweise einwandfrei, aber Sie sehen den Bereich oder den Inhalt davon nicht, wenn er mit Null Höhe, Null Breite erstellt wird.
  • Vermeiden Sie es innerhalb der Überschreibungen, der Versuchung zu erliegen, untergeordnete Elemente in FrameworkElement zu konvertieren, und verwenden Sie stattdessen Eigenschaften, die als Ergebnis des Layouts berechnet werden, insbesondere ActualWidth und ActualHeight. In den meisten gängigen Szenarien können Sie die Logik auf dem DesiredSize Wert des untergeordneten Elements basieren, und Sie benötigen keines der Height oder Width verwandten Eigenschaften eines untergeordneten Elements. Für spezielle Fälle, in denen Sie den Elementtyp kennen und zusätzliche Informationen haben, z. B. die natürliche Größe einer Bilddatei, können Sie die speziellen Informationen Ihres Elements verwenden, da es sich nicht um einen Wert handelt, der aktiv von Layoutsystemen geändert wird. Das Einschließen von layoutberechneten Eigenschaften als Teil der Layoutlogik erhöht das Risiko erheblich, eine unbeabsichtigte Layoutschleife zu definieren. Diese Schleifen verursachen eine Situation, durch die kein gültiges Layout erstellt werden kann, und das System kann eine LayoutCycleException- auslösen, wenn die Schleife nicht wiederhergestellt werden kann.
  • Panels teilen in der Regel ihren verfügbaren Platz zwischen mehreren untergeordneten Elementen auf, wobei die genaue Aufteilung des Raums variieren kann. Beispielsweise implementiert Grid eine Layoutlogik, die seine RowDefinition- und ColumnDefinition- Werte verwendet, um den Raum in die Grid Zellen aufzuteilen, wobei sowohl sterngesteuerte Größen als auch Pixelwerte unterstützt werden. Wenn es sich um Pixelwerte handelt, ist die für jedes untergeordnete Element verfügbare Größe bereits bekannt, sodass dies als Eingabegröße für ein Rasterformat Measureübergeben wird.
  • Panels selbst können reservierten Raum für den Abstand zwischen Elementen schaffen. Wenn Sie dies tun, stellen Sie sicher, dass die Maße als Eigenschaft dargestellt werden, die sich unterscheidet von Margin- oder einer Padding--Eigenschaft.
  • Elemente verfügen möglicherweise über Werte für ihre AktuelleBreite- und AktuelleHöhe- Eigenschaften auf der Grundlage eines vorherigen Layoutdurchlaufs. Wenn sich Werte ändern, kann der App-UI-Code Handler für LayoutUpdated auf den Elementen platzieren, wenn eine spezielle Logik ausgeführt werden soll. Die Panel-Logik muss jedoch in der Regel nicht auf Änderungen mit der Ereignisbehandlung überprüft werden. Das Layoutsystem bestimmt bereits, wann das Layout erneut ausgeführt werden soll, da ein layoutrelevanter Eigenschaftswert geändert wurde, und die MeasureOverride- oder ArrangeOverride- in den entsprechenden Fällen automatisch aufgerufen werden.

ArrangeOverride

Die ArrangeOverride--Methode verfügt über einen Size Rückgabewert, der vom Layoutsystem beim Rendern des Panels selbst verwendet wird, wenn die Arrange-Methode vom übergeordneten Element im Layout für das Panel aufgerufen wird. Es ist typisch, dass die Eingabe finalSize und die von ArrangeOverride zurückgegebene Size identisch sind. Wenn dies nicht der Fall ist, bedeutet das, dass das Panel versucht, eine andere Größe anzunehmen, als die von den anderen Teilnehmern des Layouts angegebene verfügbare Größe. Die endgültige Größe basiert darauf, dass Sie zuvor den Messdurchlauf des Layouts über Ihren Panelcode ausgeführt haben. Deshalb ist es nicht typisch, eine andere Größe zurückzugeben: Es bedeutet, dass Sie die Messlogik bewusst ignorieren.

Geben Sie keine Size mit einer Infinity Komponente zurück. Wenn Sie versuchen, eine solche Größe zu verwenden, löst eine Ausnahme aus dem internen Layout aus.

Alle ArrangeOverride Implementierungen sollten über Childreniterieren, um die Methode Arrange für jedes untergeordnete Element aufzurufen. Wie Measure, hat Arrange keinen Rückgabewert. Im Gegensatz zu Measurewird keine berechnete Eigenschaft als Ergebnis festgelegt (das betreffende Element löst jedoch in der Regel ein LayoutUpdated Ereignis aus).

Hier ist ein sehr einfaches Skelett einer --ArrangeOverride---Methode:

protected override Size ArrangeOverride(Size finalSize)
{
    //loop through each Child, call Arrange on each
    foreach (UIElement child in Children)
    {
        Point anchorPoint = new Point(); //TODO more logic for topleft corner placement in your panel
       // for this child, and based on finalSize or other internal state of your panel
        child.Arrange(new Rect(anchorPoint, child.DesiredSize)); //OR, set a different Size 
    }
    return finalSize; //OR, return a different Size, but that's rare
}

Der Anordnungsdurchlauf des Layouts kann passieren, ohne dass ein Measuredurchlauf vorausgeht. Dies geschieht jedoch nur, wenn das Layoutsystem festgestellt hat, dass sich keine Eigenschaften geändert haben, die sich auf die vorherigen Messungen auswirken würden. Wenn sich beispielsweise eine Ausrichtung ändert, muss das betreffende Element nicht erneut gemessen werden, da sich die DesiredSize nicht ändern würde, wenn sich die Ausrichtungsauswahl ändert. Andererseits ist ein neuer Messdurchlauf erforderlich, wenn sich ActualHeight auf ein Element in einem Layout ändert. Das Layoutsystem erkennt automatisch echte Messänderungen und ruft den Messdurchlauf erneut auf und führt dann einen weiteren Anordnungsdurchlauf aus.

Die Eingabe für Arrange akzeptiert einen Rect Wert. Die am häufigsten verwendete Methode, um dieses Rect zu erstellen, besteht darin, einen Konstruktor mit einer Point Eingabe und einer Size Eingabe zu verwenden. Der Punkt ist der Punkt, an dem die obere linke Ecke des Begrenzungsrahmens für das Element platziert werden soll. Die Size sind die Dimensionen, die zum Rendern dieses bestimmten Elements verwendet werden. Häufig verwenden Sie die DesiredSize- für dieses Element als diesen Size--Wert, da das Festlegen der DesiredSize- für alle Elemente, die am Layout beteiligt sind, der Zweck des Measuredurchlaufs des Layouts war. (Der Messdurchlauf bestimmt die gesamte Größenanpassung der Elemente auf iterative Weise, sodass das Layoutsystem optimieren kann, wie Elemente platziert werden, sobald sie zum Anordnungsdurchlauf gelangen.)

Zwischen den Implementierungen von ArrangeOverride variiert in der Regel die Logik, mit der das Panel die Point-Komponente bestimmt, um jedes untergeordnete Element anzuordnen. Ein absolutes Positionierungspanel wie Canvas verwendet die expliziten Platzierungsinformationen, die es von jedem Element über die Werte von Canvas.Left und Canvas.Top erhält. Ein raumteilendes Paneel wie Grid hätte mathematische Operationen, die den verfügbaren Platz in Zellen unterteilen, und jede Zelle hätte einen x-y-Wert, um den Inhalt zu platzieren und anzuordnen. Ein adaptives Panel wie StackPanel- kann sich erweitern, um Inhalte in die Ausrichtungsdimension einzufügen.

Es gibt immer noch zusätzliche Positionierungseinflüsse auf Elemente im Layout, jenseits dessen, was Sie direkt steuern und an Anordnenübergeben. Diese stammen aus der internen nativen Implementierung von Arrange, die allen von FrameworkElement abgeleiteten Typen gemeinsam ist und durch einige andere Typen, wie z.B. Textelemente, ergänzt wird. Beispielsweise können Elemente einen Rand und eine Ausrichtung aufweisen, und einige können einen Abstand aufweisen. Diese Eigenschaften interagieren häufig. Weitere Informationen finden Sie unter Ausrichtung, Rand und Abstand.

Paneele und Steuerelemente

Vermeiden Sie es, Funktionalität in ein benutzerdefiniertes Panel einzufügen, das stattdessen als benutzerdefiniertes Steuerelement erstellt werden sollte. Die Funktion eines Panels besteht darin, alle darin enthaltenen Elemente und Inhalte auf Grundlage eines Layouts darzustellen, das automatisch angewendet wird. Das Panel kann Dekorationen zu Inhalten hinzufügen (ähnlich wie ein Rahmen den Rahmen um das dargestellte Element hinzufügt) oder andere layoutbezogene Anpassungen wie Polsterung ausführen. Dies ist jedoch so weit, wie Sie gehen sollten, wenn Sie die visuelle Strukturausgabe über die Berichterstellung hinaus erweitern und Informationen von den untergeordneten Elementen verwenden sollten.

Wenn eine Interaktion für den Benutzer zugänglich ist, sollten Sie ein benutzerdefiniertes Steuerelement anstatt eines Panels schreiben. Beispielsweise sollte ein Panel keine Bildlaufbereiche zu den Inhalten hinzufügen, die es darstellt, selbst wenn das Ziel darin besteht, das Abschneiden zu verhindern, da Bildlaufleisten, Schieberegler usw. interaktive Steuerelemente sind. (Der Inhalt verfügt möglicherweise über Bildlaufleisten, aber Sie sollten dies der Logik des untergeordneten Elements überlassen. Erzwingen Sie dies nicht, indem Sie einen Bildlauf als Layoutvorgang hinzufügen.) Sie können ein Steuerelement erstellen und auch ein benutzerdefiniertes Panel schreiben, das eine wichtige Rolle in der visuellen Struktur dieses Steuerelements spielt, wenn es darum geht, Inhalte in diesem Steuerelement darzustellen. Das Steuerelement und das Panel sollten jedoch unterschiedliche Codeobjekte sein.

Ein Grund, warum die Unterscheidung zwischen Steuerelement und Panel wichtig ist, liegt in der Microsoft-Benutzeroberflächenautomatisierung und der Barrierefreiheit. Panels bieten ein visuelles Layoutverhalten, kein logisches Verhalten. Wie ein UI-Element visuell dargestellt wird, ist kein Aspekt der Benutzeroberfläche, der in der Regel für Barrierefreiheitsszenarien wichtig ist. Bei der Barrierefreiheit geht es darum, die Teile einer App verfügbar zu machen, die für das Verständnis einer Benutzeroberfläche logisch wichtig sind. Wenn Interaktion erforderlich ist, sollten Steuerelemente die Interaktionsmöglichkeiten für die Benutzeroberflächenautomatisierungs-Infrastruktur verfügbar machen. Weitere Informationen finden Sie unter Benutzerdefinierte Automatisierungs-Partner.

Andere Layout-API

Es gibt einige andere APIs, die Teil des Layoutsystems sind, aber nicht von Paneldeklariert werden. Sie können diese bei der Implementierung eines Panels oder in einem benutzerdefinierten Steuerelement mit Panels verwenden.

  • UpdateLayout, InvalidateMeasureund InvalidateArrange sind Methoden, die einen Layoutdurchlauf initiieren. InvalidateArrange löst möglicherweise keinen Messdurchlauf aus, die beiden anderen tun dies jedoch. Rufen Sie diese Methoden niemals innerhalb einer Layoutmethodenüberschreibung auf, da sie fast sicher sind, dass sie eine Layoutschleife verursachen. Steuerungscode muss diese in der Regel auch nicht aufrufen. Die meisten Aspekte des Layouts werden automatisch ausgelöst, indem Änderungen an den frameworkdefinierten Layouteigenschaften wie Width usw. erkannt werden.
  • LayoutUpdated ist ein Ereignis, das ausgelöst wird, wenn sich ein Aspekt des Layouts des Elements geändert hat. Dies ist nicht spezifisch für Panels; das Ereignis wird durch FrameworkElementdefiniert.
  • SizeChanged ist ein Ereignis, das nur ausgelöst wird, nachdem Layoutdurchläufe abgeschlossen wurden, und angibt, dass ActualHeight oder ActualWidth sich dadurch geändert haben. Dies ist ein weiteres FrameworkElement Ereignis. Es gibt Fälle, in denen LayoutUpdated ausgelöst wird, aber SizeChanged nicht. Beispielsweise kann der interne Inhalt neu angeordnet werden, aber die Größe des Elements hat sich nicht geändert.

Referenz

Konzepte