2010-07-16 6 views
3

Un problème est survenu avec ma liaison. Mais je ne peux pas trouverProblème de synchronisation de la liaison de données wpf

J'ai un contrôle de type d'état (UserControl) qui a un ItemsControl avec une liaison qui repose sur un objet ViewModelBase qui fournit la liste des BrokenRules, comme ceci:

<ItemsControl ItemsSource="{Binding BrokenRules}" > 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <TextBlock> 
       <Hyperlink Foreground="Red" > 
        <TextBlock Text="{Binding Description}" /> 
       </Hyperlink> 
      </TextBlock> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

La liaison fonctionne comme je le veux, dans le sens où toutes les règles brisées Descriptions sont affichées. Une règle est à peu près une simple description et un délégué est exécuté lorsque la règle est appelée à se valider elle-même.

La plupart des règles ont des Descriptions qui sont connues à l'avance, avant que la règle ne demande à se valider elle-même. Par exemple, "Nom n'est pas évalué" est une bonne description de ce qui s'est passé si le délégué de validation! Name.IsNullOrEmptyAfterTrim() échoue.

Le problème vient avec une règle particulière, qui vérifie les noms en double. Si la vérification double échoue, je veux être capable de dire quelle est la valeur dupliquée, ce qui est impossible à savoir à l'avance. La règle doit donc mettre à jour la description lorsque le délégué de validation est exécuté.

Lorsque j'effectue un test unitaire ou laisse une trace de débogage dans le délégué de validation, la description de la règle rompue est mise à jour. Mais quand je cours l'application, la description de règle cassée est ce qui était avant il a été mis à jour. Je suppose donc que ma liaison n'est pas correcte. Quelqu'un peut-il suggérer quel est le problème?

Cheers,
Berryl

MISE À JOUR ====================

C'est le code de ma classe ViewModelBase:

private readonly List<RuleBase> _rules = new List<RuleBase>(); 

// inheritors add rules as part of construction 
protected void _AddRule(RuleBase rule) { _rules.Add(rule); } 

public ObservableCollection<RuleBase> BrokenRules { get { return _brokenRules; } } 
protected ObservableCollection<RuleBase> _brokenRules; 

public virtual IEnumerable<RuleBase> GetBrokenRules()   { 
     return GetBrokenRules(string.Empty); 
} 

public virtual IEnumerable<RuleBase> GetBrokenRules(string property)  { 
    property = property.CleanString(); 

    _brokenRules = new ObservableCollection<RuleBase>(); 
    foreach (var r in _rules)   { 
     // Ensure we only validate this rule 
     if (r.PropertyName != property && property != string.Empty) continue; 

     var isRuleBroken = !r.ValidateRule(this); 

     if (isRuleBroken) _brokenRules.Add(r); 

     return _brokenRules; 
    } 
+0

Votre classe ViewModelBase implémente-t-elle INotifyPropertyChanged? c'est à dire. L'interface utilisateur sait-elle quand la propriété Description a changé? –

+0

Ajoutez-vous des éléments à la collection BrokenRules? est-ce une ObservableCollection? – Anero

+0

@Matt. Oui, VmBase implémente INPC. Pour ce qui est de la deuxième partie de votre réponse, je pense qu'Aero est proche du fait que si je ne recrée pas l'instance de collection à chaque fois, alors l'interface restera synchronisée avec les changements. Besoin de travailler à travers. Cheers – Berryl

Répondre

1

Vous devez vous assurer que la BrokenRules instance de collection observable ne change pas, votre code sur la vue modèle devrait ressembler à:

public ObservableCollection<BrokenRule> BrokenRules 
{ 
    get; 
    set; 
} 

private void ValidateRules() 
{ 
    // Validation code 
    if (!rule.IsValid) 
    { 
    this.BrokenRules.Add(new BrokenRule { Description = "Duplicated name found" }); 
    } 
} 

Si, par exemple, vous faites quelque chose comme ceci:

this.BrokenRules = this.ValidateRules(); 

Vous changerez la collection qui est lié à la ItemsControl sans le notifier et les changements ne reflètent pas l'assurance-chômage.

+0

Je pense que votre proche. Ma liste de règles brisées n'était pas une ObservableCollection ET elle crée une nouvelle instance dans chaque boucle. J'ai corrigé le type de collection, puisque c'était trivial, et je vais regarder comment faire cela avec la même instance de collection suivante.Vous devez supprimer les règles qui ne sont pas brisées et ajouter des règles brisées, ce qui n'est pas aussi trivial. Cheers – Berryl

+1

@Berryl: Au lieu de créer une nouvelle collection, vous pouvez utiliser '.Clear()'. Cela ne casse pas la liaison de données. – Jens

+0

La combinaison de tous les commentaires a fonctionné correctement. Puisque Anero avait la seule chose que je pouvais marquer comme réponse, je marquais le sien comme tel. Merci a tous! – Berryl

Questions connexes