J'implémente un Effect
ajustable par l'utilisateur en utilisant des curseurs et j'ai un bouton de réinitialisation à côté du curseur. L'idée est de permettre à l'utilisateur de revenir à la valeur par défaut de la propriété Effect
comme indiqué dans les métadonnées. Je pense qu'il pourrait être trivial de faire cela en XAML.Comment réinitialiser une DependencyProperty à sa valeur par défaut dans XAML
Répondre
Les propriétés de dépendance n'ont pas vraiment de valeurs par défaut. Si une propriété de dépendance n'a pas de valeur locale, elle obtiendra sa valeur soit par héritage de valeur, soit par coercition, selon la manière dont la propriété a été implémentée.
Vous ne pouvez pas vraiment vous débarrasser de la valeur locale de la propriété dans XAML - cela nécessiterait d'appeler ClearValue
sur la propriété, et il n'y a aucun moyen de trouver l'objet et d'appeler une méthode de façon déclarative. Mais tant que la propriété obtient sa valeur par l'héritage de valeur (au lieu de coercition de valeur), vous pouvez accomplir fondamentalement la même chose en liant la propriété à la propriété dont elle hérite sur l'ancêtre approprié. vous souhaitez utiliser pour créer un ListBox
qui définit la couleur de premier plan de tous les éléments qui ne sont pas sélectionné:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter
Property="Foreground"
Value="{Binding
RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox},
Path=Foreground}" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
Ceci implémente essentiellement explicitement l'héritage de valeur par la liaison. Cela signifie que la propriété ListBoxItem.Foreground
maintenant a une valeur locale, et que chaque fois que vous modifiez la propriété Foreground
sur le ListBox
il est obligatoire qui met à jour le ListBoxItem.Foreground
et non le système de propriété de dépendance. Cela pourrait en fait importer si vous avez des centaines de milliers d'articles dans votre ListBox
. Mais dans la plupart des cas réels, vous ne remarquerez jamais la différence.
Le problème est que cela ne fonctionne que pour WPF et SL5. SL4 n'a pas RelativeSource = FindAncestor –
Vous avez découragé l'utilisation de ClearValue. Donc j'ai fait exactement ça. – CyberFox
Afin d'éviter les cycles logiques, WPF résiste fortement aux tentatives de définition d'une valeur DependencyProperty
à sa valeur actuelle. Ceci est un problème lors de l'initialisation, où vous souhaitez que la logique dépendante soit configurée pour configurer pour la première fois en fonction du DefaultValue
enregistré dans les métadonnées, pour chacune des différentes propriétés dépendantes. WPF ne le fera pas car, dans un cas particulier, toutes ces propriétés obtiennent déjà leurs valeurs par défaut sans jamais avoir exécuté une telle logique. Pour autant que je sache, aucune combinaison de InvalidateProperty
, CoerceValue
ou ClearValue
ne convaincra WPF de faire le travail. Une correction triviale consisterait en quelque sorte à invoquer une valeur autre que la valeur par défaut sans danger pour la remplacer, puis à la réinitialiser par ClearValue
. Cela semble toutefois difficile, car il peut ne pas être pratique de déterminer une valeur «inoffensive». Peut-être pire, cette approche va inutilement onduler le graphique de dépendance deux fois, au lieu d'une seule fois. En tant que solution peut-être plus élégante, vous pouvez appeler la méthode d'extension suivante dans le constructeur de chaque objet pertinent pour appeler manuellement la logique PropertyChanged
pour chaque DependencyProperty
dont les modifications doivent être propagées. Cette aide déclenchera des modifications consécutives en fonction de la valeur par défaut stockée dans les métadonnées respectives.
public static void ResetValue(this DependencyObject _this, DependencyProperty dp)
{
var md = dp.GetMetadata(_this.GetType());
if (_this.GetValue(dp).Equals(md.DefaultValue))
{
var args = new DependencyPropertyChangedEventArgs(dp, DependencyProperty.UnsetValue, md.DefaultValue);
md.PropertyChangedCallback(_this, args);
}
else
_this.ClearValue(dp);
}
Comme le montre, la fonction inclut une vérification pour voir si ClearValue
serait en fait efficace, donc au-delà des scénarios d'initialisation, vous pouvez également utiliser cette fonction pour remplacer ClearValue
en général. Pour la clarté de la démonstration, cette méthode ne vérifie pas que l'objet hôte expose en fait une logique de changement de propriété, mais ce serait un simple changement. En C# 7, par exemple:
// ...
md.PropertyChangedCallback?.Invoke(_this, args);
Exemple d'utilisation dans votre classe:
class MyClass : DependencyObject
{
public static readonly DependencyProperty MyDp = /* ... */
public MyClass()
{
this.ResetValue(MyDp);
/* ... */
}
};
Depuis XAML est pas question de procédure ne fait pas beaucoup de sens. Essayez d'expliquer pourquoi vous voulez faire cela? – AnthonyWJones
et à quelle heure, en fonction de certaines conditions, déclencher etc? – akjoshi