2011-11-14 2 views
2

dans mon application Silverlight 4, j'ai une classe myClass qui contient une liste de element s. Ce element a un attribut name qui les identifie.Assurer des éléments uniques dans la liste avec Silverlight Databinding

class element 
{ 
    string Name { get; set; } 
} 

class myClass 
{ 
    List<element> elements { get; } 
} 

Pour afficher la liste des éléments, je Databind myClass.elements à Silverlight Listbox:

<ListBox> 
    <ListBox.ItemTemplate> 
    <DataTemplate> 
     <Grid> 
     <TextBox Text="{Binding Name, FallbackValue=[None], Mode=TwoWay, 
         NotifyOnValidationError=true, ValidatesOnExceptions=true}" /> 
... 

De cette façon, les modifications du Name du element est automatiquement propagée en arrière. Mais: je dois vous assurer que le Name est unique dans myClass.elements (et quelques autres contraintes, en fonction des propriétés de myClass

Naturellement, les éléments ne sait pas qui le contient (et il ne doit pas savoir,. Je pense.) Donc mon problème est: Comment puis-je vérifier les contraintes des éléments (dans le setter de la propriété Name)? Je voudrais vraiment utiliser le Silverlight-Databinding, car il implémente déjà la notification d'erreur

Merci à l'avance,
Frank

+0

Une question, que voulez-vous que l'application fasse si l'utilisateur tente d'entrer un doublon? Vous pouvez essayer que l'élément setter déclenche un événement auquel la classe conteneur est abonnée pour valider l'élément. – EtherDragon

+0

L'application ne doit pas enregistrer la valeur et la zone de texte doit afficher une erreur (via NotifyOnValidationError et ValidatesOnExceptions), donc je suppose que le setter aurait besoin d'augmenter l'erreur. Lorsque je lève un événement dans le setter, je ne peux plus réagir dans le setter au résultat de la validation (ne pas définir la propriété, en augmentant l'erreur), n'est-ce pas? – Aaginor

Répondre

1

Je suggère que element devrait impl ement INotifyProperyChange et myClass doivent être à l'écoute des modifications, puis vérifier les duplications, en lançant des exceptions ou en indiquant une erreur à l'aide d'IDataErrorInfo, d'INotifyDataErrorInfo ou d'un indicateur personnalisé. (donc vous implémentez le pattern Observer, je suppose, myClass ici est un observateur pour ses items).

Pour une manière personnalisée, il est possible de définir la propriété "IsDuplicate" dans des éléments en double et de la lier à la couleur d'arrière-plan (rouge). Cela pourrait être plus utile pour l'utilisateur, s'il veut intentionnellement définir un nom en double ici, puis veut corriger un élément entré auparavant. Aussi, s'il serait plus facile de trouver des doublons si vous les indiquez tous dans la liste.

MISE À JOUR:

Voici l'indication d'une erreur. L'élément juste modifié a une bordure, des doublons pour cela - police rouge.

<Style TargetType="{x:Type TextBox}"> 
    <Style.Triggers> 
     <DataTrigger Binding="{Binding Path=IsDuplicate}" Value="True"> 
      <Setter Property="Foreground" Value="Red" /> 
     </DataTrigger> 
     <Trigger Property="Validation.HasError" Value="true"> 
      <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, 
       Path=(Validation.Errors)[0].ErrorContent}"/> 
      <Setter Property="BorderBrush" Value="Red"/> 
     </Trigger> 
    </Style.Triggers> 
</Style> 

est ici modèle d'élément, notez ValidatesOnDataErrors:

<ListBox.ItemTemplate> 
     <DataTemplate> 
      <Grid> 
       <TextBox Text="{Binding Path=Name, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" /> 
      </Grid> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 

Voici votre classe Element:

class Element : INotifyPropertyChanged, IDataErrorInfo 
{ 
    private string _name; 
    public string Name 
    { 
     get { return _name; } 
     set { _name = value; 
     if(PropertyChanged != null) 
      PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name")); 
     } 
    } 

    private bool _isDuplicate; 
    public bool IsDuplicate 
    { 
     get { return _isDuplicate; } 
     set 
     { 
      _isDuplicate = value; 
      PropertyChanged.Invoke(this, new PropertyChangedEventArgs("IsDuplicate")); 
     } 
    } 
    //IDataErrorInfo 
    public event PropertyChangedEventHandler PropertyChanged; 

    public string this[string columnName] 
    { 
     get 
     { 
      if (IsDuplicate) 
       return "Duplicate col" + columnName; 
      return null; 
     } 
    } 

    public string Error 
    { 
     get { return null; } 
    } 
} 

Et enfin, myClass devrait écouter PropertyChanged et invoquer contrôle de duplication.

+0

Salut Mikalai, merci pour la réponse, cela semble être un bon moyen! Ce que je ne sais pas encore est: Quand myClass indique une erreur (de duplication), comment puis-je augmenter l'exception (IDataErrorInfo) pour l'élément, de sorte que sa zone de texte l'affiche?Actuellement, je lance une exception dans le setter des éléments, mais lorsque myClass vérifie les doublons, je ne suis plus dans le setter de l'élément. – Aaginor

+0

J'ai posté un code pour répondre au texte - j'espère que ça aide :) – mikalai

+0

Ah, très bon exemple, merci beaucoup! La mise en œuvre de IDataErrorInfo est très utile et pourrait être utile dans d'autres parties aussi bien :) – Aaginor