2010-07-28 3 views
0

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

+5

Depuis XAML est pas question de procédure ne fait pas beaucoup de sens. Essayez d'expliquer pourquoi vous voulez faire cela? – AnthonyWJones

+0

et à quelle heure, en fonction de certaines conditions, déclencher etc? – akjoshi

Répondre

4

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.

+0

Le problème est que cela ne fonctionne que pour WPF et SL5. SL4 n'a pas RelativeSource = FindAncestor –

+0

Vous avez découragé l'utilisation de ClearValue. Donc j'ai fait exactement ça. – CyberFox

1

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); 
     /* ... */ 
    } 
}; 
Questions connexes