2010-11-27 4 views
4

J'ai une liste déroulante liée à une liste d'objets. Pour chaque élément de liste je voulais avoir un rectangle dont la couleur de remplissage est déterminée par quelques propriétés de l'objet lié. J'ai donc fait ce qui suit:Pourquoi la propriété de propriété jointe a-t-elle uniquement changé l'événement?

  1. S'assurer que INotifyPropertyChanged a été implémenté sur mon objet.
  2. Création d'une classe pour exposer les propriétés qui m'intéressent en tant que propriétés attachées.
  3. Lié les propriétés de l'objet aux propriétés attachées du rectangle
  4. Créé un style qui utilise des déclencheurs pour définir le remplissage du rectangle en fonction des propriétés attachées.

Cela fonctionne, mais seulement la première fois que la propriété de l'objet change. Après cela, les propriétés jointes ne semblent pas recevoir de notification lorsque la propriété de l'objet de données change. J'ai vérifié deux fois et mon objet de données soulève l'événement INotifyPropertyChanged. Quel pourrait être le problème?

<Rectangle Style="{StaticResource RecordStateRectangleStyle}" 
       Width="10" Height="10" Stroke="Black" 
       local:RecordAttachment.RecordState="{Binding Path=RecordState}" 
       local:RecordAttachment.IsDeleted="{Binding Path=IsDeleted}" /> 

Le style:

<Style x:Key="RecordStateRectangleStyle" TargetType="Rectangle"> 
     <Style.Resources> 
      <SolidColorBrush x:Key="AddedStateBrush" Color="LightGreen" Opacity=".8" /> 
      <SolidColorBrush x:Key="ModifiedStateBrush" Color="Orange" Opacity=".8" /> 
      <SolidColorBrush x:Key="DeletedStateBrush" Color="Red" Opacity=".8" /> 
     </Style.Resources> 
     <Style.Triggers> 
      <Trigger Property="local:RecordAttachment.RecordState" Value="{x:Static model:RecordState.Added}"> 
       <Setter Property="Fill" Value="{StaticResource AddedStateBrush}" /> 
      </Trigger> 
      <Trigger Property="local:RecordAttachment.RecordState" Value="{x:Static model:RecordState.Modified}"> 
       <Setter Property="Fill" Value="{StaticResource ModifiedStateBrush}" /> 
      </Trigger> 
      <Trigger Property="local:RecordAttachment.IsDeleted" Value="true"> 
       <Setter Property="Fill" Value="{StaticResource DeletedStateBrush}" /> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 

Propriétés de la classe Ci-joint:

Public Class RecordAttachment 
Public Shared ReadOnly RecordStateProperty As DependencyProperty 
Public Shared ReadOnly IsDeletedProperty As DependencyProperty 

Shared Sub New() 
    RecordStateProperty = DependencyProperty.RegisterAttached("RecordState", _ 
                   GetType(Model.RecordState), _ 
                   GetType(RecordAttachment), _ 
                   New PropertyMetadata(Model.RecordState.Unchanged, AddressOf RecordStatePropertyChanged)) 
    IsDeletedProperty = DependencyProperty.RegisterAttached("IsDeleted", _ 
                  GetType(Boolean), _ 
                  GetType(RecordAttachment), _ 
                  New PropertyMetadata(AddressOf DeletedPropertyChanged)) 
End Sub 

Public Shared Sub SetRecordState(ByVal element As UIElement, ByVal state As Model.RecordState) 
    element.SetValue(RecordStateProperty, state) 
End Sub 
Public Shared Function GetRecordState(ByVal element As UIElement) As Model.RecordState 
    Return CType(element.GetValue(RecordStateProperty), Model.RecordState) 
End Function 

Public Shared Sub SetIsDeleted(ByVal element As UIElement, ByVal value As Boolean) 
    element.SetValue(IsDeletedProperty, value) 
End Sub 

Public Shared Function GetIsDeleted(ByVal element As UIElement) As Boolean 
    Return CType(element.GetValue(IsDeletedProperty), Boolean) 
End Function 

Public Shared Sub RecordStatePropertyChanged(ByVal sender As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs) 
    If sender IsNot Nothing Then 
     sender.SetValue(RecordStateProperty, e.NewValue) 
    End If 
End Sub 
Public Shared Sub DeletedPropertyChanged(ByVal sender As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs) 
    If sender IsNot Nothing Then 
     sender.SetValue(IsDeletedProperty, e.NewValue) 
    End If 
End Sub 
End Class 

Quelqu'un a suggéré que je posterai la version C#, si elle est ici:

public class RecordAttachment 
{ 
    public static readonly DependencyProperty RecordStateProperty; 
    public static readonly DependencyProperty IsDeletedProperty; 

    static RecordAttachment() 
    { 
     RecordStateProperty = DependencyProperty.RegisterAttached("RecordState", 
                    typeof(model.RecordState), 
                    typeof(RecordAttachment), 
                    new PropertyMetadata(model.RecordState.Unchanged, RecordStatePropertyChanged)); 
     IsDeletedProperty = DependencyProperty.RegisterAttached("IsDeleted", 
                   typeof(bool), 
                   typeof(RecordAttachment), 
                   new PropertyMetadata(DeletedPropertyChanged)); 
    } 

    public static void SetRecordState(UIElement element, model.RecordState state) 
    { 
     element.SetValue(RecordStateProperty, state); 
    } 
    public static model.RecordState GetRecordState(UIElement element) 
    { 
     return (model.RecordState)element.GetValue(RecordStateProperty); 
    } 
    public static void SetIsDeleted(UIElement element, bool value) 
    { 
     element.SetValue(IsDeletedProperty, value); 
    } 
    public static bool GetIsDeleted(UIElement element) 
    { 
     return (bool)element.GetValue(IsDeletedProperty); 
    } 

    public static void RecordStatePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 
     if (sender != null) 
      sender.SetValue(RecordStateProperty, e.NewValue); 
    } 
    public static void DeletedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 
     if (sender != null) 
      sender.SetValue(IsDeletedProperty, e.NewValue); 
    } 
} 

MISE À JOUR J'ai résolu mon problème sous-jacent de devoir changer la couleur du remplissage du rectangle en utilisant des déclencheurs de données au lieu d'utiliser les propriétés attachées et les déclencheurs réguliers. Je voudrais toujours savoir pourquoi l'événement 'propertychanged' de la propriété attachée est seulement déclenché une fois.

J'ai fait quelques recherches supplémentaires et je suis tombé sur ce link où Josh Smith dit 'Une propriété attachée ne peut être définie que sur un élément.'. Je l'ai regardé autour et je ne peux trouver aucune explication ...

+0

@Cooper - Votre XAML semble être bien, mais encore je vous donne une suggestion; ce sera tout simplement génial si vous pouvez poster votre code en C#! Je pense que vous aurez plus de réponses et je serai en mesure de vous aider! Je suis très mauvais à VB !! J'ai essayé de convertir votre code en C# en utilisant l'outil en ligne mais il me donne quelques erreurs comme 'sub not found' ou alors et je n'ai aucune idée de VB! Ce sera tout simplement génial si vous pouvez convertir votre code en C# et le poster ici avec votre code VB :) – GuruC

+0

@GuruC - J'ai posté C#, je n'ai pas eu l'occasion de le tester, mais je suis à peu près sûr qu'il est équivalent à la version VB. –

Répondre

13

Le problème est causé par ces lignes de code dans les gestionnaires de changement de propriété:

sender.SetValue(RecordStateProperty, e.NewValue) 

et

sender.SetValue(IsDeletedProperty, e.NewValue) 

En appelant SetValue, vous définissez une nouvelle valeur locale sur la cible. La définition d'une valeur locale remplace toute liaison de données qui aurait pu être en place auparavant. En résumé, votre gestionnaire de changement de propriété supprime la liaison de données pour cette propriété.

Étant donné que vous supprimez effectivement la liaison, votre propriété ne changera plus lorsque la source de données sera modifiée car elle n'est plus la source de données pour cette propriété.

Une notification de changement de propriété est juste cela - elle vous indique que la valeur de la propriété change. Vous n'avez pas besoin de faire quoi que ce soit en réponse à cela si vous ne le souhaitez pas, et en particulier, ce n'est pas votre responsabilité de faire changer la propriété. Cela va changer de toute façon.

2

En plus de réponse choisie, cela peut aussi être résolu en utilisant

Sender.SetCurrentValue(IsDeletedProperty, e.NewValue) 

Cela va changer la valeur de la dépendance sans changer la source

Questions connexes