Benutzerdefinierte angefügte EigenschaftenCustom attached properties

Eine angefügte Eigenschaft ist ein XAML-Konzept.An attached property is a XAML concept. Angefügte Eigenschaften werden in der Regel als eine spezialisierte Form der Abhängigkeitseigenschaft definiert.Attached properties are typically defined as a specialized form of dependency property. In diesem Thema wird erläutert, wie eine angefügte Eigenschaft als Abhängigkeitseigenschaft implementiert und die Accessorkonvention definiert wird, die erforderlich ist, damit die angefügte Eigenschaft in XAML verwendet werden kann.This topic explains how to implement an attached property as a dependency property and how to define the accessor convention that is necessary for your attached property to be usable in XAML.

VoraussetzungenPrerequisites

Wir gehen davon aus, dass Sie die Abhängigkeitseigenschaften aus der Perspektive eines Consumers vorhandener Abhängigkeitseigenschaften sehen und dass Sie die Übersicht über Abhängigkeitseigenschaften gelesen haben.We assume that you understand dependency properties from the perspective of a consumer of existing dependency properties, and that you have read the Dependency properties overview. Sie sollten auch die Übersicht über angefügte Eigenschaften gelesen haben.You should also have read Attached properties overview. Für ein besseres Verständnis der in diesem Thema aufgeführten Beispiele sollten Sie XAML verstehen und wissen, wie eine einfache Windows-Runtime-App mit C++, C# oder Visual Basic geschrieben wird.To follow the examples in this topic, you should also understand XAML and know how to write a basic Windows Runtime app using C++, C#, or Visual Basic.

Szenarien für angefügte EigenschaftenScenarios for attached properties

Möglicherweise möchten Sie eine angefügte Eigenschaft erstellen, wenn es einen Grund für das Vorhandensein eines Mechanismus zum Festlegen von Eigenschaften für Klassen außer der definierenden Klasse gibt.You might create an attached property when there is a reason to have a property-setting mechanism available for classes other than the defining class. Die häufigsten Szenarien dafür sind Layout- und Dienstunterstützung.The most common scenarios for this are layout and services support. Beispiele für vorhandene Layouteigenschaften sind Canvas.ZIndex und Canvas.Top.Examples of existing layout properties are Canvas.ZIndex and Canvas.Top. In einem Layoutszenario können Elemente, die als untergeordnete Elemente für layoutsteuernde Elemente fungieren, einzeln Layoutanforderungen gegenüber ihren übergeordneten Elementen ausdrücken. Dabei legt jedes Element einen Eigenschaftswert fest, den das übergeordnete Element als eine angefügte Eigenschaft definiert.In a layout scenario, elements that exist as child elements to layout-controlling elements can express layout requirements to their parent elements individually, each setting a property value that the parent defines as an attached property. Ein Beispiel für das Dienstunterstützungsszenario in der Windows-Runtime-API ist das Festlegen der angefügten Eigenschaften von ScrollViewer, z. B. ScrollViewer.IsZoomChainingEnabled.An example of the services-support scenario in the Windows Runtime API is set of the attached properties of ScrollViewer, such as ScrollViewer.IsZoomChainingEnabled.

Warnung

Eine vorhandene Einschränkung der Windows-Runtime XAML-Implementierung besteht darin, dass Sie die benutzerdefinierte angefügte Eigenschaft nicht animieren können.An existing limitation of the Windows Runtime XAML implementation is that you cannot animate your custom attached property.

Registrieren einer benutzerdefinierten angefügten EigenschaftRegistering a custom attached property

Wenn Sie die angefügte Eigenschaft immer für die Verwendung mit anderen Typen definieren, muss die Klasse, in der die Eigenschaft registriert ist, nicht aus DependencyObject abgeleitet werden.If you are defining the attached property strictly for use on other types, the class where the property is registered does not have to derive from DependencyObject. Die Zielparameter für Accessoren müssen jedoch DependencyObject verwenden, wenn Sie das typische Modell befolgen, bei dem Ihre angefügte Eigenschaft auch eine Abhängigkeitseigenschaft sein kann, sodass Sie den Sicherungseigenschaftsspeicher verwenden können.But you do need to have the target parameter for accessors use DependencyObject if you follow the typical model of having your attached property also be a dependency property, so that you can use the backing property store.

Sie definieren Ihre angefügte Eigenschaft als Abhängigkeitseigenschaft, indem Sie eine public static readonly-Eigenschaft des Typs DependencyProperty deklarieren.Define your attached property as a dependency property by declaring a public static readonly property of type DependencyProperty. Sie definieren diese Eigenschaft mithilfe des Rückgabewerts der RegisterAttached-Methode.You define this property by using the return value of the RegisterAttached method. Der Eigenschaftenname muss mit dem Namen der angefügten Eigenschaft übereinstimmen, die Sie als RegisterAttached name-Parameter angeben. Am Ende muss die Zeichenfolge „Property“ hinzugefügt sein.The property name must match the attached property name you specify as the RegisterAttached name parameter, with the string "Property" added to the end. Dies ist die bestehende Konvention zum Benennen der Bezeichner von Abhängigkeitseigenschaften im Verhältnis mit den Eigenschaften, die sie darstellen.This is the established convention for naming the identifiers of dependency properties in relation to the properties that they represent.

Der Hauptunterschied beim Definieren einer benutzerdefinierten Eigenschaft und beim Definieren einer benutzerdefinierten Abhängigkeitseigenschaft besteht darin, wie Sie die Accessoren oder Wrapper definieren.The main area where defining a custom attached property differs from a custom dependency property is in how you define the accessors or wrappers. Anstatt die unter Benutzerdefinierte Abhängigkeitseigenschaften beschriebene Wrappertechnik zu verwenden, müssen Sie auch statische GetPropertyName- und SetPropertyName-Methoden als Accessoren für die angefügte Eigenschaft bereitstellen.Instead of the using the wrapper technique described in Custom dependency properties, you must also provide static GetPropertyName and SetPropertyName methods as accessors for the attached property. Die Accessoren werden hauptsächlich vom XAML-Parser verwendet, obwohl sie auch von anderen aufrufenden Elementen verwendet werden können, um Werte in Nicht-XAML-Szenarien festzulegen.The accessors are used mostly by the XAML parser, although any other caller can also use them to set values in non-XAML scenarios.

Wichtig

Wenn Sie die Accessoren nicht ordnungsgemäß definieren, kann der XAML-Prozessor nicht auf die angefügte Eigenschaft zugreifen, und jeder, der versucht, ihn zu verwenden, erhält wahrscheinlich einen XAML-Parserfehler.If you don't define the accessors correctly, the XAML processor can't access your attached property and anyone who tries to use it will probably get a XAML parser error. Entwurfs-und Codierungs Tools basieren außerdem häufig auf den " * Property"-Konventionen für Benennungs Bezeichner, wenn Sie eine benutzerdefinierte Abhängigkeits Eigenschaft in einer Assembly finden, auf die verwiesen wird.Also, design and coding tools often rely on the "*Property" conventions for naming identifiers when they encounter a custom dependency property in a referenced assembly.

AccessorenAccessors

Die Signatur für den GetPropertyName-Accessor lautet folgendermaßen.The signature for the GetPropertyName accessor must be this.

public static valueType GetPropertyName (DependencyObject target)public static valueType GetPropertyName (DependencyObject target)

Bei Microsoft Visual Basic lautet sie folgendermaßen.For Microsoft Visual Basic, it is this.

Public Shared Function GetPropertyName (ByVal target As DependencyObject) As ValueType)Public Shared Function GetPropertyName(ByVal target As DependencyObject) As valueType)

Das target-Objekt kann in Ihrer Implementierung einen spezielleren Typ aufweisen, muss jedoch von DependencyObject abgeleitet sein.The target object can be of a more specific type in your implementation, but must derive from DependencyObject. Der valueType-Rückgabewert kann in Ihrer Implementierung auch einen spezielleren Typ aufweisen.The valueType return value can also be of a more specific type in your implementation. Der grundlegende Object-Typ wird akzeptiert. Häufig soll jedoch Ihre angefügte Eigenschaft Typsicherheit erzwingen.The basic Object type is acceptable, but often you'll want your attached property to enforce type safety. Die Verwendung der Typisierung in den Getter- und Setter-Signaturen ist eine empfohlene Typsicherheitstechnik.The use of typing in the getter and setter signatures is a recommended type-safety technique.

Die Signatur für den SetPropertyName-Accessor lautet folgendermaßen.The signature for the SetPropertyName accessor must be this.

public static void SetPropertyName (DependencyObject target , ValueType value)public static void SetPropertyName(DependencyObject target ,valueType value)

Bei Microsoft Visual Basic lautet sie folgendermaßen.For Visual Basic, it is this.

Public Shared Sub SetPropertyName (ByVal target As DependencyObject, ByVal value As ValueType)Public Shared Sub SetPropertyName(ByVal target As DependencyObject, ByVal value AsvalueType)

Das target-Objekt kann in Ihrer Implementierung einen spezielleren Typ aufweisen, muss jedoch von DependencyObject abgeleitet sein.The target object can be of a more specific type in your implementation, but must derive from DependencyObject. Das value-Objekt und dessen valueType können in Ihrer Implementierung einen spezielleren Typ aufweisen.The value object and its valueType can be of a more specific type in your implementation. Beachten Sie, dass der Wert für diese Methode die Eingabe ist, die vom XAML-Prozessor stammt, wenn er Ihre angefügte Eigenschaft im Markup feststellt.Remember that the value for this method is the input that comes from the XAML processor when it encounters your attached property in markup. Die Typkonvertierung oder vorhandene Markuperweiterung muss für den von Ihnen verwendeten Typ unterstützt werden, damit der entsprechende Typ auf der Grundlage eines Attributwerts (der letztlich nur eine Zeichenfolge ist) erstellt werden kann.There must be type conversion or existing markup extension support for the type you use, so that the appropriate type can be created from an attribute value (which is ultimately just a string). Der grundlegende Object-Typ ist akzeptabel. Häufig möchten Sie jedoch zusätzliche Typsicherheit erreichen.The basic Object type is acceptable, but often you'll want further type safety. Versehen Sie hierzu die Accessoren mit einer Typerzwingung.To accomplish that, put type enforcement in the accessors.

Hinweis

Es ist auch möglich, eine angefügte Eigenschaft zu definieren, bei der die beabsichtigte Verwendung über die Syntax von Eigenschafts Elementen erfolgt.It's also possible to define an attached property where the intended usage is through property element syntax. In diesem Fall benötigen Sie keine Typkonvertierung für die Werte. Sie müssen allerdings sicherstellen, dass die beabsichtigten Werte in XAML konstruierbar sind.In that case you don't need type conversion for the values, but you do need to assure that the values you intend can be constructed in XAML. VisualStateManager.VisualStateGroups ist ein Beispiel für eine vorhandene angefügte Eigenschaft, die nur die Eigenschaftselementverwendung unterstützt.VisualStateManager.VisualStateGroups is an example of an existing attached property that only supports property element usage.

CodebeispielCode example

In diesem Beispiel werden die Abhängigkeitseigenschaftsregistrierung (mithilfe der RegisterAttached-Methode) sowie die Accessoren Get und Set für eine benutzerdefinierte angefügte Eigenschaft dargestellt.This example shows the dependency property registration (using the RegisterAttached method), as well as the Get and Set accessors, for a custom attached property. Im Beispiel ist der Name der angefügten Eigenschaft IsMovable.In the example, the attached property name is IsMovable. Deshalb müssen die Accessoren GetIsMovable und SetIsMovable genannt werden.Therefore, the accessors must be named GetIsMovable and SetIsMovable. Der Besitzer der angefügten Eigenschaft ist eine Dienstklasse mit dem Namen GameService, die nicht über eine eigene Benutzeroberfläche verfügt. Sie dient lediglich zur Bereitstellung der Dienste der angefügten Eigenschaft, wenn die angefügte Eigenschaft GameService.IsMovable verwendet wird.The owner of the attached property is a service class named GameService that doesn't have a UI of its own; its purpose is only to provide the attached property services when the GameService.IsMovable attached property is used.

Das Definieren der angefügten-Eigenschaft in C++/CX ist etwas komplexer.Defining the attached property in C++/CX is a bit more complex. Sie müssen entscheiden, wie die Faktorverteilung zwischen der Header- und Codedatei lauten soll.You have to decide how to factor between the header and code file. Außerdem sollten Sie den Bezeichner als Eigenschaft mit nur einem get-Accessor verfügbar machen. Die Gründe hierfür werden unter Benutzerdefinierte Abhängigkeitseigenschaften erläutert.Also, you should expose the identifier as a property with only a get accessor, for reasons discussed in Custom dependency properties. In C++/CX müssen Sie diese Eigenschafts Feld Beziehung explizit definieren, anstatt sich auf die Schreib geschützte Schlüssel Formulierung von .net und die implizite Unterstützung von einfachen Eigenschaften zu verlassen.In C++/CX you must define this property-field relationship explicitly rather than relying on .NET readonly keywording and implicit backing of simple properties. Sie müssen auch die Registrierung der angefügten Eigenschaft innerhalb einer Hilfsfunktion durchführen, die nur einmal ausgeführt wird; dies erfolgt beim ersten Start der App, jedoch bevor XAML-Seiten geladen werden, die die angefügte Eigenschaft benötigen.You also need to perform the registration of the attached property within a helper function that only gets run once, when the app first starts but before any XAML pages that need the attached property are loaded. Der typische Ort, um die Hilfsobjekte für die Eigenschaften Registrierung für alle Abhängigkeiten oder angefügten Eigenschaften aufzurufen, liegt innerhalb des App- / anwendungskonstruktors im Code für die Datei "App. XAML".The typical place to call your property registration helper functions for any and all dependency or attached properties is from within the App / Application constructor in the code for your app.xaml file.

public class GameService : DependencyObject
{
    public static readonly DependencyProperty IsMovableProperty = 
    DependencyProperty.RegisterAttached(
      "IsMovable",
      typeof(Boolean),
      typeof(GameService),
      new PropertyMetadata(false)
    );
    public static void SetIsMovable(UIElement element, Boolean value)
    {
        element.SetValue(IsMovableProperty, value);
    }
    public static Boolean GetIsMovable(UIElement element)
    {
        return (Boolean)element.GetValue(IsMovableProperty);
    }
}
Public Class GameService
    Inherits DependencyObject

    Public Shared ReadOnly IsMovableProperty As DependencyProperty = 
        DependencyProperty.RegisterAttached("IsMovable",  
        GetType(Boolean), 
        GetType(GameService), 
        New PropertyMetadata(False))

    Public Shared Sub SetIsMovable(ByRef element As UIElement, value As Boolean)
        element.SetValue(IsMovableProperty, value)
    End Sub

    Public Shared Function GetIsMovable(ByRef element As UIElement) As Boolean
        GetIsMovable = CBool(element.GetValue(IsMovableProperty))
    End Function
End Class
// GameService.idl
namespace UserAndCustomControls
{
    [default_interface]
    runtimeclass GameService : Windows.UI.Xaml.DependencyObject
    {
        GameService();
        static Windows.UI.Xaml.DependencyProperty IsMovableProperty{ get; };
        static Boolean GetIsMovable(Windows.UI.Xaml.DependencyObject target);
        static void SetIsMovable(Windows.UI.Xaml.DependencyObject target, Boolean value);
    }
}

// GameService.h
...
    static Windows::UI::Xaml::DependencyProperty IsMovableProperty() { return m_IsMovableProperty; }
    static bool GetIsMovable(Windows::UI::Xaml::DependencyObject const& target) { return winrt::unbox_value<bool>(target.GetValue(m_IsMovableProperty)); }
    static void SetIsMovable(Windows::UI::Xaml::DependencyObject const& target, bool value) { target.SetValue(m_IsMovableProperty, winrt::box_value(value)); }

private:
    static Windows::UI::Xaml::DependencyProperty m_IsMovableProperty;
...

// GameService.cpp
...
Windows::UI::Xaml::DependencyProperty GameService::m_IsMovableProperty =
    Windows::UI::Xaml::DependencyProperty::RegisterAttached(
        L"IsMovable",
        winrt::xaml_typename<bool>(),
        winrt::xaml_typename<UserAndCustomControls::GameService>(),
        Windows::UI::Xaml::PropertyMetadata{ winrt::box_value(false) }
);
...
// GameService.h
#pragma once

#include "pch.h"
//namespace WUX = Windows::UI::Xaml;

namespace UserAndCustomControls {
    public ref class GameService sealed : public WUX::DependencyObject {
    private:
        static WUX::DependencyProperty^ _IsMovableProperty;
    public:
        GameService::GameService();
        void GameService::RegisterDependencyProperties();
        static property WUX::DependencyProperty^ IsMovableProperty
        {
            WUX::DependencyProperty^ get() {
                return _IsMovableProperty;
            }
        };
        static bool GameService::GetIsMovable(WUX::UIElement^ element) {
            return (bool)element->GetValue(_IsMovableProperty);
        };
        static void GameService::SetIsMovable(WUX::UIElement^ element, bool value) {
            element->SetValue(_IsMovableProperty,value);
        }
    };
}

// GameService.cpp
#include "pch.h"
#include "GameService.h"

using namespace UserAndCustomControls;

using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Documents;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Interop;
using namespace Windows::UI::Xaml::Media;

GameService::GameService() {};

GameService::RegisterDependencyProperties() {
    DependencyProperty^ GameService::_IsMovableProperty = DependencyProperty::RegisterAttached(
         "IsMovable", Platform::Boolean::typeid, GameService::typeid, ref new PropertyMetadata(false));
}

Festlegen der benutzerdefinierten angefügten Eigenschaft aus dem XAML-MarkupSetting your custom attached property from XAML markup

Hinweis

Wenn Sie C++/WinRT verwenden, fahren Sie mit dem folgenden Abschnitt fort (Festlegen der benutzerdefinierten angefügten Eigenschaft Imperativ mit C++/WinRT).If you're using C++/WinRT, then skip to the following section (Setting your custom attached property imperatively with C++/WinRT).

Nachdem Sie die angefügte Eigenschaft definiert und ihre unterstützenden Elemente als Teil des benutzerdefinierten Typs eingefügt haben, müssen Sie die Definitionen anschließend für die Verwendung von XAML verfügbar machen.After you have defined your attached property and included its support members as part of a custom type, you must then make the definitions available for XAML usage. Dazu müssen Sie einen XAML-Namespace zuordnen, der auf den Codenamespace mit der relevanten Klasse verweist.To do this, you must map a XAML namespace that will reference the code namespace that contains the relevant class. In Fällen, in denen Sie die angefügte Eigenschaft als Teil einer Bibliothek definiert haben, müssen Sie diese Bibliothek als Teil des App-Pakets für die App einfügen.In cases where you have defined the attached property as part of a library, you must include that library as part of the app package for the app.

Eine XML-Namespacezuordnung wird in der Regel im Stammelement einer XAML-Seite platziert.An XML namespace mapping for XAML is typically placed in the root element of a XAML page. Für die Klasse mit dem Namen GameService im Namespace UserAndCustomControls, der die in den vorherigen Ausschnitten dargestellten Definitionen der angefügten Eigenschaften enthält, sieht die Zuordnung z. B. folgendermaßen aus.For example, for the class named GameService in the namespace UserAndCustomControls that contains the attached property definitions shown in preceding snippets, the mapping might look like this.

<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:uc="using:UserAndCustomControls"
  ... >

Mithilfe der Zuordnung können Sie die angefügte GameService.IsMovable -Eigenschaft für beliebige Elemente festlegen, die Ihrer Zieldefinition entsprechen. Dies schließt auch einen vorhandenen von Windows-Runtime definierten Typ mit ein.Using the mapping, you can set your GameService.IsMovable attached property on any element that matches your target definition, including an existing type that Windows Runtime defines.

<Image uc:GameService.IsMovable="True" .../>

Wenn Sie die Eigenschaft für ein Element festlegen, das sich auch im selben zugeordneten XML-Namespace befindet, müssen Sie das Präfix dennoch in den Namen der angefügten Eigenschaft einfügen.If you are setting the property on an element that is also within the same mapped XML namespace, you still must include the prefix on the attached property name. Das liegt daran, dass das Präfix den Besitzertyp qualifiziert.This is because the prefix qualifies the owner type. Es kann nicht angenommen werden, dass sich das Attribut der angefügten Eigenschaft innerhalb desselben XML-Namespace wie das Element befindet, in dem das Attribut enthalten ist, auch wenn Attribute gemäß normalen XML-Regeln Namespaces von Elementen erben können.The attached property's attribute cannot be assumed to be within the same XML namespace as the element where the attribute is included, even though, by normal XML rules, attributes can inherit namespace from elements. Wenn Sie beispielsweise GameService.IsMovable für einen benutzerdefinierten Typ von ImageWithLabelControl (Definition nicht dargestellt) festlegen, sieht das XAML-Element nach wie vor folgendermaßen aus, auch wenn beide im selben Codenamespace definiert und demselben Präfix zugeordnet sind.For example, if you are setting GameService.IsMovable on a custom type of ImageWithLabelControl (definition not shown), and even if both were defined in the same code namespace mapped to same prefix, the XAML would still be this.

<uc:ImageWithLabelControl uc:GameService.IsMovable="True" .../>

Hinweis

Wenn Sie eine XAML-Benutzeroberfläche mit C++/CX schreiben, müssen Sie den-Header für den benutzerdefinierten Typ einschließen, der die angefügte-Eigenschaft definiert, wenn eine XAML-Seite diesen Typ verwendet.If you are writing a XAML UI with C++/CX, then you must include the header for the custom type that defines the attached property, any time that a XAML page uses that type. Jede XAML-Seite verfügt über einen zugeordneten Code-Behind-Header (. XAML. h).Each XAML page has an associated code-behind header (.xaml.h). An dieser Stelle sollten Sie den Header für die Definition des Besitzer Typs der angefügten Eigenschaft einschließen (mithilfe von ** # include**).This is where you should include (using #include) the header for the definition of the attached property's owner type.

Imperativ Festlegen der benutzerdefinierten angefügten Eigenschaft mit C++/WinRTSetting your custom attached property imperatively with C++/WinRT

Wenn Sie C++/WinRT verwenden, können Sie auf eine benutzerdefinierte angefügte Eigenschaft aus imperativem Code, jedoch nicht aus XAML-Markup zugreifen.If you're using C++/WinRT, then you can access a custom attached property from imperative code, but not from XAML markup. Der folgende Code zeigt die Vorgehensweise.The code below shows how.

<Image x:Name="gameServiceImage"/>
// MainPage.h
...
#include "GameService.h"
...

// MainPage.cpp
...
MainPage::MainPage()
{
    InitializeComponent();

    GameService::SetIsMovable(gameServiceImage(), true);
}
...

Werttyp einer benutzerdefinierten angefügten EigenschaftValue type of a custom attached property

Der Typ, der als Werttyp einer benutzerdefinierten angefügten Eigenschaft verwendet wird, wirkt sich auf die Nutzung, die Definition oder auf beides aus.The type that is used as the value type of a custom attached property affects the usage, the definition, or both the usage and definition. Der Werttyp der angefügten Eigenschaft wird an verschiedenen Stellen deklariert: in den Signaturen der Get- und Set-Accessormethoden und im propertyType-Parameter des RegisterAttached-Aufrufs.The attached property's value type is declared in several places: in the signatures of both the Get and Set accessor methods, and also as the propertyType parameter of the RegisterAttached call.

Der häufigste Werttyp für angefügte Eigenschaften (benutzerdefinierte oder andere) ist eine einfache Zeichenfolge.The most common value type for attached properties (custom or otherwise) is a simple string. Das liegt daran, dass angefügte Eigenschaften in der Regel für die Nutzung mit XAML-Attributen vorgesehen sind, und durch die Verwendung einer Zeichenfolge als Werttyp bleiben die Eigenschaften einfach.This is because attached properties are generally intended for XAML attribute usage, and using a string as the value type keeps the properties lightweight. Andere Grundtypen, die über eine systemeigene Konvertierung in Zeichenfolgenmethoden verfügen (z. B. eine ganze Zahl, ein Double oder ein Enumerationswert), werden ebenfalls häufig als Werttypen für angefügte Eigenschaften verwendet.Other primitives that have native conversion to string methods, such as integer, double, or an enumeration value, are also common as value types for attached properties. Sie können andere Werttypen – die die systemeigene Zeichenfolgekonvertierung nicht unterstützen – als Wert der angefügten Eigenschaft verwenden.You can use other value types—ones that don't support native string conversion—as the attached property value. Dies hat jedoch zur Folge, dass eine Auswahl in Bezug auf die Nutzung oder Implementierung getroffen werden muss:However, this entails making a choice about either the usage or the implementation:

  • Sie können die angefügte Eigenschaft so belassen, wie sie ist. Dann kann die angefügte Eigenschaft die Nutzung nur unterstützen, wenn die angefügte Eigenschaft ein Eigenschaftselement darstellt und der Wert als Objektelement deklariert wurde.You can leave the attached property as it is, but the attached property can support usage only where the attached property is a property element, and the value is declared as an object element. In diesem Fall muss der Eigenschaftstyp die XAML-Nutzung als Objektelement unterstützen.In this case, the property type does have to support XAML usage as an object element. Überprüfen Sie bei vorhandenen Windows-Runtime-Referenzklassen die XAML-Syntax, um sicherzustellen, dass der Typ die XAML-Objektelementnutzung unterstützt.For existing Windows Runtime reference classes, check the XAML syntax to make sure that the type supports XAML object element usage.
  • Sie können die angefügte Eigenschaft so belassen, wie sie ist. Dann können Sie diese jedoch nur in einer Attributnutzung über eine XAML-Referenztechnik wie Binding oder StaticResource verwenden, die als Zeichenfolge ausgedrückt werden kann.You can leave the attached property as it is, but use it only in an attribute usage through a XAML reference technique such as a Binding or StaticResource that can be expressed as a string.

Weitere Informationen zum Canvas.Left-BeispielMore about the Canvas.Left example

In vorherigen Beispielen für die Nutzung angefügter Eigenschaften wurden verschiedene Methoden zum Festlegen der angefügten Eigenschaft Canvas.Left gezeigt.In earlier examples of attached property usages we showed different ways to set the Canvas.Left attached property. Doch wie wirkt sich dies auf die Interaktionen einer Canvas mit Ihrem Objekt aus, und wann tritt dies auf?But what does that change about how a Canvas interacts with your object, and when does that happen? Wir schauen uns dieses bestimmte Beispiel genauer an. Es ist beim Implementieren einer angefügten Eigenschaft interessant zu wissen, wozu eine typische Besitzerklasse der angefügten Eigenschaft die Werte der angefügten Eigenschaft außerdem verwendet, wenn sie diese in anderen Objekten findet.We'll examine this particular example further, because if you implement an attached property, it's interesting to see what else a typical attached property owner class intends to do with its attached property values if it finds them on other objects.

Eine Canvas dient hauptsächlich dazu, einen Layoutcontainer mit absoluter Position auf der UI darzustellen.The main function of a Canvas is to be an absolute-positioned layout container in UI. Die untergeordneten Elemente einer Canvas werden in der definierten Basisklasseneigenschaft Children gespeichert.The children of a Canvas are stored in a base-class defined property Children. Canvas verwendet als einziges Panel eine absolute Positionierung.Of all the panels Canvas is the only one that uses absolute positioning. Das Objektmodell des allgemeinen UIElement-Typs würde übermäßig aufgebläht werden, wenn Eigenschaften hinzugefügt werden, die nur für Canvas und die speziellen UIElement-Fälle wichtig wären, in denen diese untergeordnete Elemente eines UIElement sind.It would've bloated the object model of the common UIElement type to add properties that might only be of concern to Canvas and those particular UIElement cases where they are child elements of a UIElement. Wenn Sie die Eigenschaften von Layoutsteuerelementen einer Canvas als angefügte Eigenschaften definieren, die von allen UIElement-Elementen verwendet werden können, ist das Objektmodell übersichtlicher.Defining the layout control properties of a Canvas to be attached properties that any UIElement can use keeps the object model cleaner.

Um als Panel praktikabel zu sein, besitzt Canvas Verhaltensweisen, die die Frameworkmethoden Measure und Arrange überschreiben.In order to be a practical panel, Canvas has behavior that overrides the framework-level Measure and Arrange methods. Hier wird von Canvas nach Werten der angefügten Eigenschaftswerte für ihre untergeordneten Elemente gesucht.This is where Canvas actually checks for attached property values on its children. Ein Teil der Muster Measure und Arrange ist eine Schleife, die alle Inhalte durchläuft. Ein Panel besitzt die Eigenschaft Children, die explizit angibt, was als untergeordnetes Element eines Panels gelten soll.Part of both the Measure and Arrange patterns is a loop that iterates over any content, and a panel has the Children property that makes it explicit what's supposed to be considered the child of a panel. Das Canvas-Layoutverhalten durchläuft diese untergeordneten Elemente und führt statische Canvas.GetLeft- und Canvas.GetTop-Aufrufe für alle untergeordneten Elemente aus, um zu ermitteln, ob diese angefügten Eigenschaften einen nicht standardmäßigen Wert enthalten (der standardmäßige Wert ist 0).So the Canvas layout behavior iterates through these children, and makes static Canvas.GetLeft and Canvas.GetTop calls on each child to see whether those attached properties contain a non-default value (default is 0). Mithilfe dieser Werte werden die untergeordneten Elemente auf der verfügbaren Canvas-Layoutfläche gemäß den von den einzelnen untergeordneten Elementen bereitgestellten spezifischen Werten absolut positioniert. Anschließend wird mithilfe von Arrange ein Commit für sie ausgeführt.These values are then used to absolutely position each child in the Canvas available layout space according to the specific values provided by each child, and committed using Arrange.

Der Code sieht in etwa wie dieser Pseudocode aus.The code looks something like this pseudocode.

protected override Size ArrangeOverride(Size finalSize)
{
    foreach (UIElement child in Children)
    {
        double x = (double) Canvas.GetLeft(child);
        double y = (double) Canvas.GetTop(child);
        child.Arrange(new Rect(new Point(x, y), child.DesiredSize));
    }
    return base.ArrangeOverride(finalSize); 
    // real Canvas has more sophisticated sizing
}

Hinweis

Weitere Informationen zur Funktionsweise von Panels finden Sie unter Übersicht über XAML Custom Panels.For more info on how panels work, see XAML custom panels overview.