Priorität von Abhängigkeitseigenschaftswerten

In diesem Thema wird erläutert, wie die Funktionsweise des Windows Presentation Foundation (WPF)-Eigenschaftensystems den Wert einer Abhängigkeitseigenschaft beeinflussen kann. Außerdem wird die Rangfolge beschrieben, nach der Aspekte des Eigenschaftensystems auf den effektiven Wert einer Eigenschaft angewendet werden.

Voraussetzungen

In diesem Thema wird davon ausgegangen, dass Sie Abhängigkeitseigenschaften aus Sicht eines Consumers vorhandener Abhängigkeitseigenschaften von WPF-Klassen verstehen und die Übersicht über Abhängigkeitseigenschaften gelesen haben. Um den Beispielen in diesem Thema zu folgen, sollten Sie zudem XAML verstehen und wissen, wie WPF-Anwendungen geschrieben werden.

Das WPF-Eigenschaftensystem

Das WPF-Eigenschaftensystem bietet eine leistungsstarke Möglichkeit, den Wert von Abhängigkeitseigenschaften durch eine Vielzahl von Faktoren zu bestimmen, wobei Funktionen wie die Validierung von Eigenschaften in Echtzeit, die späte Bindung und das Benachrichtigen von verknüpften Eigenschaften über Änderungen an Werten für andere Eigenschaften aktiviert werden. Die genaue Reihenfolge und Logik, die zur Bestimmung der Werte von Abhängigkeitseigenschaften verwendet werden, ist relativ komplex. Indem Sie diese Reihenfolge kennen, können Sie unnötige Eigenschafteneinstellungen vermeiden und klären, wieso genau ein Versuch zur Beeinflussung oder zum Vorhersehen eines Werts einer Abhängigkeitseigenschaft nicht zum erwarteten Wert geführt hat.

Abhängigkeitseigenschaften können an mehreren Orten festgelegt („Set“) werden

In der folgenden Beispiel-XAML hat die gleiche Eigenschaft (Background) drei verschiedene „Set“-Vorgänge, die sich auf den Wert auswirken könnten.

<StackPanel>
    <StackPanel.Resources>
        <ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
            <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" 
                    BorderBrush="{TemplateBinding BorderBrush}">
                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
            </Border>
        </ControlTemplate>
    </StackPanel.Resources>

    <Button Template="{StaticResource ButtonTemplate}" Background="Red">
        <Button.Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Background" Value="Blue"/>
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="Yellow" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
        Which color do you expect?
    </Button>
</StackPanel>

Was erwarten Sie, welche Farbe hier angewendet wird – rot, grün oder blau?

Mit Ausnahme von animierten Werten und Koersion werden lokale Eigenschaftensätze mit der höchsten Priorität festgelegt. Wenn Sie einen Wert lokal festlegen, können Sie erwarten, dass der Wert selbst vor Stilen oder Steuerelementvorlagen berücksichtigt wird. Hier im Beispiel ist Background lokal auf Rot eingestellt. Daher hat der in diesem Bereich definierte Stil, auch wenn es ein impliziter Stil ist, der ansonsten für alle Elemente dieses Typs in diesem Bereich gelten würde, nicht oberste Priorität bei der Vergabe des Werts der Eigenschaft Background. Wenn Sie den lokalen Wert „Red“ von dieser Schaltflächeninstanz entfernt hätten, hätte der Stil Vorrang, und die Schaltfläche würde den „Background“-Wert vom Stil erhalten. Innerhalb des Stils haben Trigger Vorrang, sodass die Schaltfläche blau sein wird, wenn die Maus darauf zeigt, und andernfalls grün.

Rangfolgeliste bei der Einstellung von Abhängigkeitseigenschaften

Im Folgenden finden Sie die definitive Reihenfolge, die vom Eigenschaftensystem beim Zuweisen der Laufzeitwerte von Abhängigkeitseigenschaften verwendet wird. Die oberste Priorität ist zuerst aufgeführt. Diese Liste erweitert einige der Verallgemeinerungen aus der Übersicht über Abhängigkeitseigenschaften.

  1. Eigenschaftensystemkoersion. Weitere Informationen zur Koersion finden Sie unter Koersion, Animationen und Basiswert weiter unten in diesem Thema.

  2. Aktive Animationen oder Animationen mit einem Halteverhalten. Damit eine Animation einer Eigenschaft eine praktische Auswirkung hat, muss sie Vorrang vor dem (nicht animierten) Basiswert haben können, selbst wenn dieser Wert lokal festgelegt wurde. Weitere Informationen finden Sie unter Koersion, Animationen und Basiswert weiter unten in diesem Thema.

  3. Lokaler Wert. Ein lokaler Wert könnte durch die „wrapper“-Eigenschaft festgelegt werden, was dem Festlegen als Attribut oder Eigenschaftenelement in XAML oder dem Aufrufen der SetValue-API mithilfe einer Eigenschaft einer bestimmten Instanz entspricht. Wenn Sie einen lokalen Wert mithilfe einer Bindung oder eine Ressource festlegen, haben diese jeweils Vorrang, als ob ein direkter Wert festgelegt wurde.

  4. TemplatedParent-Vorlageneigenschaften. Ein Element hat ein TemplatedParent, wenn es als Teil einer Vorlage erstellt wurde (ein ControlTemplate oder DataTemplate). Weitere Informationen dazu, wann dies zutrifft, finden Sie unter TemplatedParent weiter unten in diesem Thema. Innerhalb der Vorlage gilt die folgende Rangfolge:

    1. Auslöser aus der TemplatedParent-Vorlage.

    2. Eigenschaftssätze (in der Regel über XAML-Attribute) in der TemplatedParent-Vorlage.

  5. Impliziter Stil. Gilt nur für die Style-Eigenschaft. Die Style-Eigenschaft wird durch eine Stilressource mit einem Schlüssel gefüllt, der mit dem Typ dieses Elements übereinstimmt. Diese Stilressource muss entweder auf der Seite oder in der Anwendung vorhanden sein. Die Suche nach einer impliziten Stilressource wird nicht in den Designs fortgesetzt.

  6. Stiltrigger. Die Trigger innerhalb von Stilen einer Seite oder Anwendung (bei diesen Stilen kann es sich entweder um explizite oder um implizite Stile, jedoch nicht um Standardstile handeln, die in der Rangfolge weiter unten stehen).

  7. Vorlagentrigger. Ein Trigger aus einer Vorlage innerhalb eines Stils oder eine direkt angewendete Vorlage.

  8. Stil-Setter. Werte aus einer Setter innerhalb von Stilen einer Seite oder Anwendung.

  9. Standard(design)stil. Ausführliche Informationen dazu, wann dies zutrifft und wie sich Designstile auf die Vorlagen innerhalb von Designstilen beziehen, finden Sie unter Standard(design)stile weiter unten in diesem Thema. Innerhalb eines Standardstils gilt die folgende Rangfolge:

    1. Aktive Trigger im Designstil

    2. Setter im Designstil

  10. Vererbung. Einige Abhängigkeitseigenschaften vererben ihre Werte von übergeordneten Elementen an untergeordnete Elemente, sodass sie nicht speziell für jedes Element in einer Anwendung festgelegt werden müssen. Weitere Informationen finden Sie unter Vererbung von Eigenschaftswerten.

  11. Standardwert von den Metadaten der Abhängigkeitseigenschaft. Jede Abhängigkeitseigenschaft kann einen Standardwert haben, wie bei der Registrierung der bestimmten Eigenschaft durch das Eigenschaftensystem festgelegt. Außerdem verfügen abgeleitete Klassen, die eine Abhängigkeitseigenschaft erben, über die Option zum Überschreiben dieser Metadaten (einschließlich des Standardwerts) auf einer Pro-Typ-Basis. Weitere Informationen finden Sie unter Metadaten für Abhängigkeitseigenschaften. Da die Vererbung vor dem Standardwert überprüft wird, hat bei einer vererbten Eigenschaft der Standardwert eines übergeordneten Elements Vorrang vor einem untergeordneten Element. Daher wird, wenn eine vererbbare Eigenschaft nicht irgendwo festgelegt ist, der Standardwert verwendet, der im Stamm oder übergeordneten Element festgelegt wurde, anstatt des Standardwerts des untergeordneten Elements.

TemplatedParent

TemplatedParent als Rangfolgenelement gilt für keine Eigenschaft eines Elements, das Sie direkt in Standardanwendungsmarkup deklarieren. Das TemplatedParent-Konzept besteht nur für untergeordnete Elemente in einer visuellen Struktur, die durch die Anwendung der Vorlage erstellt werden. Wenn das Eigenschaftensystem die Vorlage TemplatedParent nach einem Wert durchsucht, durchsucht es die Vorlage, die das Element erstellt hat. Die Eigenschaftswerte aus der Vorlage TemplatedParent verhalten sich in der Regel so, als ob sie als lokalen Wert auf dem untergeordneten Element festgelegt wurden. Diese geringere Priorität gegenüber dem lokalen Wert besteht jedoch, da die Vorlagen potenziell geteilt werden. Ausführliche Informationen finden Sie unter TemplatedParent.

Die Style-Eigenschaft

Die zuvor beschriebene Reihenfolge gilt für alle möglichen Abhängigkeitseigenschaften, außer einer: die Style-Eigenschaft. Die Style-Eigenschaft ist in der Hinsicht einzigartig, dass sie nicht selbst gestaltet werden kann, weshalb die Rangfolgenelemente 5 bis 8 nicht angewendet werden. Außerdem ist es nicht empfehlenswert, Style entweder zu animieren oder zu erzwingen (und die Animation von Style würde eine eigene Animationsklasse erfordern). Es gibt also drei Möglichkeiten, die Style-Eigenschaft zu setzen:

  • Expliziter Stil. Die Style-Eigenschaft wird direkt festgelegt. In den meisten Szenarios wird der Stil nicht inline definiert, aber stattdessen durch einen expliziten Schlüssel als eine Ressource verwiesen. In diesem Fall verhält sich die Style-Eigenschaft selbst so, als handele es sich um einen lokalen Wert, das Rangfolgenelement 3.

  • Impliziter Stil. Die Style-Eigenschaft wird nicht direkt festgelegt. Die Style-Eigenschaft ist jedoch auf einer bestimmten Ebene in der Ressourcensuchsequenz (Seite, Anwendung) vorhanden, und es wird ein Schlüssel mithilfe eines zum anzuwendenden Stiltyp passenden Ressourcenschlüssels zugewiesen. In diesem Fall verhält sich die Style-Eigenschaft selbst als in der Sequenz als Element 5 identifizierte Priorität. Diese Bedingung können Sie feststellen, indem Sie DependencyPropertyHelper gegen die Style-Eigenschaft verwenden und in den Ergebnissen nach ImplicitStyleReference nachsehen.

  • Standardformat, auch als Designformat bezeichnet. Die Style Eigenschaft wird nicht direkt festgelegt, und tatsächlich null wird es bis zur Laufzeit gelesen. In diesem Fall stammt der Stil von der Auswertung des Laufzeitdesigns, die Teil der WPF-Präsentations-Engine ist.

Bei impliziten Stilen außerhalb von Designs muss der Typ genau übereinstimmen – eine abgeleitete MyButtonButton-Klasse verwendet nicht implizit einen Stil für Button.

Standard(design)stile

Jedes Steuerelement, das WPF umfasst, verfügt über einen Standardstil. Der Standardstil variiert möglicherweise nach Design, weshalb dieser Standardstil manchmal auch als Designstil bezeichnet wird.

Die wichtigste Information, die im Standardstil eines Steuerelements gefunden wird, ist dessen Steuerelementvorlage, die im Designstil als Setter für die Template-Eigenschaft vorhanden ist. Wenn keine Vorlage von Standardstilen vorhanden wäre, hätte ein Steuerelement ohne eine benutzerdefinierte Vorlage als Teil eines benutzerdefinierten Stils überhaupt keine visuelle Darstellung. Die Vorlage des Standardstils gibt der visuellen Darstellung jedes Steuerelements eine grundlegende Struktur und definiert zudem die Verbindungen zwischen Eigenschaften, die in der visuellen Struktur der Vorlage und der entsprechenden Steuerelementklasse definiert werden. Jedes Steuerelement macht einen Satz von Eigenschaften verfügbar, die die visuelle Darstellung des Steuerelements beeinflussen können, ohne die Vorlage komplett zu ersetzen. Betrachten wir zum Beispiel die Standarddarstellung eines Thumb-Steuerelements, das eine Komponente eines ScrollBar ist.

Ein Thumb hat bestimmte anpassbare Eigenschaften. Die Standardvorlage eines Thumb erstellt eine Grundstruktur / einen visuellen Baum mit mehreren verschachtelten Border-Komponenten, um ein schräges Aussehen zu erzeugen. Wenn eine Eigenschaft, die Teil der Vorlage ist, für die Anpassung durch die Thumb-Klasse verfügbar gemacht werden soll, muss diese Eigenschaft durch eine TemplateBinding innerhalb der Vorlage verfügbar gemacht werden. Im Fall von Thumb teilen sich verschiedene Eigenschaften dieser Ränder eine Vorlagenbindung mit Eigenschaften wie Background oder BorderThickness. Bestimmte andere Eigenschaften oder visuelle Anordnungen sind in der Steuerelementvorlage hartcodiert oder an Werte gebunden, die direkt aus diesem Design stammen. Diese können nicht ersetzt werden, ohne die gesamte Vorlage zu ersetzen. Im Allgemeinen gilt, dass eine Eigenschaft, die von einem vorlagenbasierten übergeordneten Element stammt und nicht von einer Vorlagenbindung verfügbar gemacht wird, nicht durch Stile angepasst werden kann, da nicht auf einfache Weise auf sie abgezielt werden kann. Diese Eigenschaft kann jedoch trotzdem durch die Eigenschaftswertvererbung in der angewandten Vorlage oder durch den Standardwert beeinflusst werden.

Die Designstile verwenden einen Typ als Schlüssel in ihren Definitionen. Wenn jedoch Designs auf eine bestimmte Elementinstanz angewendet werden, wird die Designsuche für diesen Typ durch Überprüfen der DefaultStyleKey-Eigenschaft auf einem Steuerelement ausgeführt. Dies steht im Gegensatz zur Verwendung des Literaltyps, wie es bei impliziten Stilen der Fall ist. Der Wert der DefaultStyleKey-Eigenschaft würde selbst dann an abgeleitete Klassen vererben, wenn sie durch die Implementierung nicht geändert wurde (die vorgesehene Weise, die Eigenschaft zu ändern, ist nicht, sie auf Eigenschaftsebene zu überschreiben, sondern stattdessen ihren Standardwert in Eigenschaftsmetadaten zu ändern). Diese Dereferenzierung ermöglicht Basisklassen, die Designstile für abgeleitete Elemente zu definieren, die andernfalls über keinen Stil verfügen (oder noch wichtiger: die über keine Vorlage innerhalb dieses Stils verfügen und somit überhaupt keine visuelle Standarddarstellung haben würden). Sie können also MyButton von Button ableiten und erhalten trotzdem dieButton- Standardvorlage. Wenn Sie der Autor des Steuerelements von MyButton wären und ein anderes Verhalten wünschten, könnten Sie die Metadaten der Abhängigkeitseigenschaft für DefaultStyleKey auf MyButton überschreiben, um einen anderen Schlüssel zurückzugeben, und anschließend die entsprechenden Designstile, einschließlich der Vorlage für MyButton, definieren, die Sie mit Ihrem MyButton-Steuerelement zusammenpacken müssen. Weitere Informationen über Designs, Stile und das Erstellen von Steuerelementen finden Sie unter Übersicht über das Erstellen von Steuerelementen.

Dynamische Ressourcenverweise und Binden

Dynamische Ressourcenverweise und Bindungsvorgänge berücksichtigen die Rangfolge des Speicherorts, an dem sie festgelegt werden. Beispielsweise fungiert eine dynamische Ressource, die auf einen lokalen Wert angewendet wird, als Rangfolgenelement 3, eine Bindung für einen Eigenschaften-Setter innerhalb eines Designstils gilt als Rangfolgenelement 9 usw. Da sowohl dynamische Ressourcenreferenzen als auch das Binden Werte aus dem Laufzeitzustand der Anwendung abrufen können muss, hat dies zur Folge, dass der eigentliche Prozess der Bestimmung der Eigenschaftswert-Rangfolge für eine bestimmte Eigenschaft ebenfalls auf die Laufzeit ausgeweitet wird.

Dynamische Ressourcenverweise sind streng genommen nicht Teil des Eigenschaftensystems, sie verfügen jedoch über eine eigene Suchreihenfolge, die mit der oben aufgeführten Sequenz interagiert. Diese Rangfolge ist in den XAML-Ressourcen genauer dokumentiert. Die grundlegende Zusammenfassung dieser Rangfolge ist: Element zu Seitenstamm, Anwendung, Design, System.

Dynamische Ressourcen und Bindungen verwenden die Rangfolge von wo sie festgelegt wurden, der Wert ist jedoch zurückgestellt. Eine Folge dessen ist, dass wenn Sie eine dynamische Ressource oder Bindung für einen lokalen Wert festlegen, jede Änderung am lokalen Wert die dynamische Ressource oder Bindung vollständig ersetzt. Selbst wenn Sie die ClearValue-Methode aufrufen, um den lokal festgelegten Wert zu löschen, wird die dynamische Ressource oder Bindung nicht wiederhergestellt. Wenn Sie eine ClearValue-Eigenschaft aufrufen, für die eine dynamische Ressource oder eine Bindung vorhanden ist (ohne einen wörtlichen lokalen Wert), werden auch diese durch den ClearValue-Aufruf gelöscht.

SetCurrentValue

Die SetCurrentValue-Methode ist eine weitere Möglichkeit, eine Eigenschaft festzulegen, aber sie steht nicht in der Rangfolge. Stattdessen ermöglicht SetCurrentValue Ihnen, den Wert einer Eigenschaft zu ändern, ohne die Quelle eines vorherigen Werts zu überschreiben. Sie können SetCurrentValue immer, wenn Sie einen Wert festlegen möchten, ohne diesem Wert die Priorität eines lokalen Werts zu geben. Wenn beispielsweise eine Eigenschaft durch einen Trigger festgelegt wird und ihr dann durch SetCurrentValue ein anderer Wert zugewiesen wird, berücksichtigt das Eigenschaftensystem trotzdem den Trigger, und die Eigenschaft ändert sich, wenn die Aktion des Triggers erfolgt. SetCurrentValue ermöglicht es Ihnen, den Wert der Eigenschaft zu ändern, ohne ihr eine Quelle mit einer höheren Priorität zuzuweisen. Ebenso können Sie mit SetCurrentValue den Wert einer Eigenschaft ändern, ohne eine Bindung zu überschreiben.

Koersion, Animationen und Basiswert

Sowohl Koersion als auch Animation wirken auf einen Wert, der in diesem SDK als „Basiswert“ bezeichnet wird. Der Basiswert ist daher der Wert, der dadurch bestimmt wird, dass in den Elementen von unten nach oben geprüft wird, bis das Element 2 erreicht wird.

Bei einer Animation kann sich der Basiswert auf den animierten Wert auswirken, wenn diese Animation nicht sowohl „From“ (Von) als auch „To“ (Zu) für bestimmte Verhalten angibt, oder wenn die Animation nach Abschluss bewusst auf den Basiswert zurücksetzt. Um dies in der Praxis nachzuvollziehen, führen Sie das Beispiel für From-, To- und By-Animationszielwerte aus. Versuchen Sie, die lokalen Werte für die Höhe des Rechtecks im Beispiel so festzulegen, dass sich der ursprüngliche lokale Wert von jedem „From“-Wert in der Animation unterscheidet. Sie werden feststellen, dass die Animationen sofort starten, die „From“-Werte verwenden und den Basiswert ersetzen. Die Animation könnte angeben, dass zu dem Wert zurückgekehrt wird, der vor der Animation aufgefunden wurde, sobald diese abgeschlossen ist, indem Stop FillBehavior angegeben wird. Anschließend wird die normale Rangfolge für die Bestimmung des Basiswerts verwendet.

Möglicherweise werden mehrere Animationen auf eine einzelne Eigenschaft angewendet, wobei jede dieser Animationen von verschiedenen Punkten in der Wertrangfolge definiert sein kann. Jedoch setzen diese Animationen möglicherweise ihre Werte zusammen, anstatt nur die Animation der höheren Priorität anzuwenden. Dies hängt davon ab, wie die Animationen genau definiert sind, sowie vom Typ des Werts, der animiert wird. Weitere Informationen über das Animieren von Eigenschaften finden Sie unter Übersicht über Animationen.

Die Koersion gilt auf der höchsten Ebene von allen. Selbst eine bereits ausgeführte Animation unterliegt der Koersion des Werts. Bestimmte vorhandene Abhängigkeitseigenschaften in WPF verfügen über eine integrierte Koersion. Bei einer benutzerdefinierten Abhängigkeitseigenschaft definieren Sie das Koersionsverhalten für eine benutzerdefinierte Abhängigkeitseigenschaft, indem Sie ein CoerceValueCallback-Delegat schreiben und den Rückruf als Teil der Metadaten übergeben, wenn Sie die Eigenschaft erstellen. Sie können das Koersionsverhalten vorhandener Eigenschaften auch überschreiben, indem Sie die Metadaten dieser Eigenschaft in einer abgeleiteten Klasse überschreiben. Die Koersion interagiert so mit dem Basiswert, dass die zum diesem Zeitpunkt vorliegenden Einschränkungen der Koersion angewendet werden, der Basiswert jedoch trotzdem erhalten bleibt. Wenn Einschränkungen der Koersion später angehoben werden, gibt die Koersion daher den Wert zurück, der diesem Basiswert am nächsten liegt, und der Einfluss der Koersion auf eine Eigenschaft wird möglicherweise gestoppt, sobald alle Einschränkungen angehoben wurden. Weitere Informationen zum Koersionsverhalten finden Sie unter Rückrufe und Validierung von Abhängigkeitseigenschaften.

Triggerverhalten

Steuerelemente definieren Triggerverhalten häufig als Teil ihres Standardstils in Designs. Durch das Festlegen von lokalen Eigenschaften für Steuerelemente wird möglicherweise verhindert, dass die Trigger entweder über die Darstellung oder das Verhalten auf benutzergesteuerte Ereignisse reagieren können. Die häufigste Verwendung eines Eigenschafts-Triggers ist für Kontroll- oder Statuseigenschaften wie IsSelected. Wenn z. B. ein Button standardmäßig deaktiviert ist (Auslöser für IsEnabled ist false), dann ist es der Foreground-Wert im Designstil, der das Steuerelement "ausgegraut" erscheinen lässt. Wenn Sie jedoch einen lokalen Foreground-Wert festgelegt haben, wird diese ausgegraute Farbe in der Rangfolge durch Ihre lokal festgelegte Eigenschaft aufgehoben, selbst in diesem durch die Eigenschaft ausgelösten Szenario. Seien Sie vorsichtig mit dem Festlegen von Werten für Eigenschaften, die über Triggerverhalten auf Designebene verfügen, und stellen Sie sicher, dass Sie nicht in die vorgesehene Benutzerfreundlichkeit dieses Steuerelements eingreifen.

ClearValue und Wertrangfolge

Die ClearValue-Methode bietet ein sinnvolles Mittel zum Löschen von lokal angewendeten Werten einer Abhängigkeitseigenschaft, die für ein Element festgelegt ist. Das Aufrufen von ClearValue ist jedoch keine Garantie dafür, dass der während der Eigenschaftsregistrierung in den Metadaten festgelegte Standard der neue effektive Wert ist. Alle anderen Teilnehmer der Wertrangfolge sind noch immer aktiv. Nur der lokal festgelegte Wert wurde von der Rangfolgensequenz entfernt. Wenn Sie z. B. ClearValue für eine Eigenschaft aufrufen, wobei diese Eigenschaft auch durch einen Designstil festgelegt ist, gilt der Designwert anstelle des metadatenbasierten Standards als der neue Wert. Wenn Sie alle Eigenschaftswerteteilnehmer aus dem Prozess nehmen und den Wert auf den registrierten Metadatenstandard festlegen möchten, können Sie diesen Standardwert definitiv abrufen, indem Sie die Metadaten der Abhängigkeitseigenschaft abfragen und den Standardwert anschließend dazu verwenden, die Eigenschaft durch einen Aufruf von SetValue lokal festzulegen.

Weitere Informationen