Quelle est la différence entre une propriété de dépendance et une propriété attachée dans WPF?

91

Quelle est la différence entre une propriété de dépendance (personnalisée) et une propriété jointe dans WPF? Quelles sont les utilisations de chacun? En quoi les implémentations diffèrent-elles généralement?

Kenwarner
la source

Réponses:

20

Abstrait

Comme je n'ai trouvé que peu ou pas de documentation sur le sujet, il a fallu un peu de fouille dans le code source , mais voici une réponse.

Il y a une différence entre l'enregistrement d'une propriété de dépendance en tant que propriété régulière et en tant que propriété jointe, autre qu'une propriété "philosophique" ( les propriétés régulières sont destinées à être utilisées par le type déclarant et ses types dérivés, les propriétés jointes sont destinées à être utilisées comme extensions sur des DependencyObject instances arbitraires ). "Philosophique", car, comme @MarqueIV l'a remarqué dans son commentaire à la réponse de @ ReedCopsey, les propriétés régulières peuvent également être utilisées avec des DependencyObjectinstances arbitraires .

De plus, je ne suis pas d'accord avec les autres réponses indiquant que la propriété attachée est un "type de propriété de dépendance", car c'est trompeur - il n'y a pas de "types" de propriétés de dépendance. Le cadre ne se soucie pas de savoir si la propriété a été enregistrée comme attachée ou non - il n'est même pas possible de déterminer (dans le sens où cette information n'est pas enregistrée, car elle n'est pas pertinente). En fait, toutes les propriétés sont enregistrées comme si elles étaient des propriétés attachées, mais dans le cas des propriétés normales, certaines choses supplémentaires sont effectuées qui modifient légèrement leur comportement.

Extrait de code

Pour vous éviter de parcourir le code source vous-même, voici une version résumée de ce qui se passe.

Lors de l'enregistrement d'une propriété sans métadonnées spécifiées, appel

DependencyProperty.Register(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass))

donne exactement le même résultat que l'appel

DependencyProperty.RegisterAttached(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass))

Cependant, lors de la spécification des métadonnées, l'appel

DependencyProperty.Register(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass),
    typeMetadata: new FrameworkPropertyMetadata
    {
        CoerceValueCallback = CoerceCallback,
        DefaultValue = "default value",
        PropertyChangedCallback = ChangedCallback
    });

équivaut à appeler

var property = DependencyProperty.RegisterAttached(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass),
    defaultMetadata: new PropertyMetadata
    {
        DefaultValue = "default value",
    });
property.OverrideMetadata(
    forType: typeof(MyClass),
    typeMetadata: new FrameworkPropertyMetadata
    {
        CoerceValueCallback = CoerceCallback,
        DefaultValue = "default value",
        PropertyChangedCallback = ChangedCallback
    });

Conclusions

La principale différence (et unique) entre les propriétés de dépendance normales et attachées réside dans les métadonnées par défaut disponibles via la propriété DependencyProperty.DefaultMetadata . Ceci est même mentionné dans la section Remarques :

Pour les propriétés non attachées, le type de métadonnées renvoyé par cette propriété ne peut pas être converti en types dérivés de type PropertyMetadata , même si la propriété a été initialement inscrite avec un type de métadonnées dérivé. Si vous souhaitez que les métadonnées enregistrées à l'origine incluent leur type de métadonnées d'origine éventuellement dérivé, appelez plutôt GetMetadata (Type) , en transmettant le type d'enregistrement d'origine en tant que paramètre.

Pour les propriétés attachées, le type des métadonnées renvoyées par cette propriété correspondra au type indiqué dans la méthode d'inscription RegisterAttached d' origine .

Ceci est clairement visible dans le code fourni. De petits indices sont également cachés dans les méthodes d'enregistrement, c'est-à-dire que RegisterAttachedle paramètre de métadonnées est nommé defaultMetadata, alors que pour Registerlui est nommé typeMetadata. Pour les propriétés jointes, les métadonnées fournies deviennent les métadonnées par défaut. Cependant, dans le cas de propriétés normales, les métadonnées par défaut sont toujours une nouvelle instance de PropertyMetadataavec uniquement DefaultValuedéfini (soit à partir des métadonnées fournies, soit automatiquement). Seul l'appel suivant à OverrideMetadatautilise réellement les métadonnées fournies.

Conséquences

La principale différence pratique est que dans le cas de propriétés régulières, les CoerceValueCallbacket PropertyChangedCallbackne s'appliquent qu'aux types dérivés du type déclaré comme type de propriétaire, et aux propriétés attachées, ils s'appliquent à tous les types. Par exemple, dans ce scénario:

var d = new DependencyObject();
d.SetValue(SomeClass.SomeProperty, "some value");

la propriété enregistrée PropertyChangedCallback sera appelée si la propriété a été enregistrée comme propriété attenante, mais ne sera pas appelée si elle a été enregistrée comme propriété ordinaire. Il en va de même CoerceValueCallback.

Une différence secondaire provient du fait que OverrideMetadatanécessite que le type fourni dérive DependencyObject. En pratique, cela signifie que le type de propriétaire pour les propriétés régulières doit dériver de DependencyObject, alors que pour les propriétés attachées, in peut être n'importe quel type (y compris les classes statiques, les structures, les énumérations, les délégués, etc.).

Supplément

Outre la suggestion de @ MarqueIV, j'ai rencontré à plusieurs reprises des opinions selon lesquelles les propriétés régulières et attachées diffèrent dans la façon dont elles peuvent être utilisées en XAML . À savoir, que les propriétés régulières nécessitent une syntaxe de nom implicite par opposition à une syntaxe de nom explicite requise par les propriétés attachées. Ce n'est techniquement pas vrai , même si dans la pratique c'est généralement le cas. Pour plus de clarté:

<!-- Implicit property name -->
<ns:SomeClass SomeProperty="some value" /> 

<!-- Explicit property name -->
<DependencyObject ns:SomeClass.SomeProperty="some value" />

En XAML pur , les seules règles régissant l'utilisation de ces syntaxes sont les suivantes:

  • La syntaxe de nom implicite peut être utilisée sur un élément si et seulement si la classe que cet élément représente a une propriété CLR de ce nom
  • La syntaxe de nom explicite peut être utilisée sur un élément si et seulement si la classe spécifiée par la première partie du nom complet expose les méthodes get / set statiques appropriées (appelées accesseurs ) avec des noms correspondant à la deuxième partie du nom complet

Le respect de ces conditions vous permet d'utiliser la syntaxe correspondante, que la propriété de dépendance de support ait été enregistrée comme régulière ou attachée.

Maintenant, l'idée fausse mentionnée est causée par le fait que la grande majorité des didacticiels (ainsi que des extraits de code Visual Studio ) vous demandent d'utiliser la propriété CLR pour les propriétés de dépendance normales et d'obtenir / définir des accesseurs pour ceux qui sont attachés. Mais rien ne vous empêche d'utiliser les deux en même temps, vous permettant d'utiliser la syntaxe que vous préférez.

Grx70
la source
71

Les propriétés jointes sont un type de propriété de dépendance. La différence réside dans la façon dont ils sont utilisés.

Avec une propriété jointe, la propriété est définie sur une classe qui n'est pas la même classe pour laquelle elle est utilisée. Ceci est généralement utilisé pour la mise en page. De bons exemples sont Panel.ZIndex ou Grid.Row - vous appliquez ceci à un contrôle (par exemple: Button), mais il est en fait défini dans Panel ou Grid. La propriété est "attachée" à l'instance du bouton.

Cela permet à un conteneur, par exemple, de créer des propriétés qui peuvent être utilisées sur n'importe quel élément UI.

En ce qui concerne les différences d'implémentation, il s'agit simplement d'utiliser Register vs RegisterAttached lorsque vous définissez la propriété.

Reed Copsey
la source
10
Mais quelle est exactement la différence?! D'après ce que j'ai vu, vous pouvez attacher une propriété non attachable à une autre via le code (je pense que cela est bloqué en XAML cependant.) C'est peut-être la différence?
Mark A. Donohoe
5

Les propriétés attachées sont essentiellement destinées aux éléments du conteneur, comme si vous avez une grille et que vous avez grid.row maintenant, cela est considéré comme une propriété attachée d'un élément de grille.Vous pouvez également utiliser cette propriété dans texbox, bouton, etc.pour définir son place dans la grille.

La propriété de dépendance est comme la propriété appartient fondamentalement à une autre classe et est utilisée dans une autre classe. par exemple: comme vous avez un rectangle ici, la hauteur et la largeur sont des propriétés régulières du rectangle, mais left et top sont la propriété de dépendance car elle appartient à la classe Canvass.

shweta
la source
-1

Les propriétés jointes sont un type spécial de DependencyProperties. Ils vous permettent d'attacher une valeur à un objet qui ne sait rien de cette valeur. Les panneaux de disposition sont un bon exemple de ce concept. Chaque panneau de disposition a besoin de données différentes pour aligner ses éléments enfants. Le canevas a besoin du haut et de la gauche, le DockPanel a besoin du Dock, etc. Puisque vous pouvez écrire votre propre panneau de mise en page, la liste est infinie. Vous voyez donc qu'il n'est pas possible d'avoir toutes ces propriétés sur tous les contrôles WPF. La solution sont des propriétés attachées. Ils sont définis par le contrôle qui a besoin des données d'un autre contrôle dans un contexte spécifique. Par exemple, un élément aligné par un panneau de disposition parent.

Mukesh
la source
-1

Je pense que vous pouvez définir la propriété jointe dans la classe elle-même ou vous pouvez la définir dans une autre classe. Nous pourrions toujours utiliser la propriété jointe pour étendre les contrôles Microsoft standard. Mais propriété de dépendance, vous la définissez dans votre propre contrôle personnalisé. Par exemple, vous pouvez hériter de votre contrôle d'un contrôle standard, définir une propriété de dépendance dans votre propre contrôle et l'utiliser. Cela équivaut à définir une propriété jointe et à utiliser cette propriété jointe dans le contrôle standard.

spspli
la source