2010-07-18 2 views
2

J'ai le problème: J'ai quelques contrôles sur un formulaire (une case à cocher, une combo-box, un curseur, une zone de texte). Leurs valeurs sont liées à différentes propriétés du modèle de vue.
Lorsqu'une propriété du modèle de vue a une certaine valeur, I veut que ces contrôles soient "corrigés" (un message d'erreur est affiché et ils sont réglés sur une valeur fixe (par exemple: la case n'est pas cochée lorsque l'utilisateur essaie de le vérifier, le curseur est défini sur une certaine valeur, l'élément sélectionné du combo est le deuxième élément de la liste) Je l'ai fait de cette façon (un exemple simplifié pour la zone de texte): Dans la vue:Forcer la mise à jour de la vue sur l'erreur de validation en utilisant le modèle MVVM

  <TextBox 
       Text="{Binding ViewModelProperty, 
           NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, 
           ValidatesOnDataErrors=True, NotifyOnValidationError=True}" 
       /> 

Dans le modèle de vue: la propriété est définie comme suit:

String _ViewModelProperty; 
public String ViewModelProperty 
{ 
    get 
    { 
     return _ViewModelProperty; 
    } 
    set 
    { 

     _ViewModelProperty = value; 
     OnPropertyChanged("ViewModelProperty"); 
    } 
} 

et la mise en œuvre de IDataErrorInfo:

String IDataErrorInfo.this[String propertyName] 
{ 
    get 
    { 
     String error = null; 
     if (propertyName == "ViewModelProperty") 
     { 
      if (ViewModelProperty != "FixedValue") 
      { 
       error = DisplayMessage("You can only set a fixed value here"); 
       ViewModelProperty= "FixedValue"; 
      } 
     } 
     return error; 
    } 
} 

Cela fonctionne bien pour la case, mais pour toutes les autres commandes, il fonctionne comme ceci: l'utilisateur définit la valeur « mauvaise », le message d'erreur est affiché puis, au lieu de mettre à jour le contrôle avec la valeur fixe, la valeur erronée est toujours affichée (elle n'est plus synchronisée avec le modèle de vue).

Je n'arrive pas à comprendre comment forcer une mise à jour de la valeur du contrôle.

Merci d'avance.

+0

Pourquoi autorisez-vous l'utilisateur à changer le contrôle, s'il est réparé ce qui est autorisé? – Goblin

Répondre

0

Vous pouvez lier les propriétés IsEnabled des contrôles que vous souhaitez corriger à un ensemble de propriétés sur ViewModel, tel que CanUserChangeSlider.

<Slider IsEnabled={Binding CanUserChangeSlider} ... /> 

Ainsi, dans le setter pour la propriété liée Comboboxes:

set 
{ 
    // store value in backing store 
    // RaisePropertyChanged 

    if (value == true) 
    { 
    this.CanUserChangeSlider = false; 
    // the bound property for slider set to certain value 
    // the bound property for combobox changed to be a certain value 
    } 
} 
0

La façon de forcer la re-bind est d'appeler BindingExpression.UpdateTarget() ou BindingExpression.UpdateSource(), selon le cas.

Bien sûr, vous ne voulez pas cela dans votre view-model.

Depuis que j'injecte vue-modèles dans mes vues, et les définir comme DataContext dans le constructeur de vue, je ferais quelque chose comme ce qui suit:

  • déclare un délégué ou d'un événement sur le point de vue-modèle sera appelé ou en relief à partir de poseurs de propriété lorsque les données sont sous la contrainte
  • dans le constructeur de vue, attacher un gestionnaire au délégué qui appellera les méthodes de mise à jour appropriées comme décrit ci-dessus (également remplacer Dispose() et supprimer le gestionnaire)

Fondamentalement, il suffit de déclencher un événement à chaque fois que les données sont forcées, et de transmettre les données dont la vue aura besoin de se reconnecter au modèle de vue.

Cela ne me vient pas à l'esprit, je n'ai donc pas défini les paramètres dont vous pourriez avoir besoin dans la signature du délégué, ni la mesure dans laquelle le gestionnaire peut fonctionner avec tous vos champs. C'est peut-être un point de départ, cependant.

0

Je n'utilise pas la propriété IsEnabled, car il s'agit des conditions requises: rien n'est désactivé, seul le message s'affiche si des valeurs "non valides" sont définies.
L'autre exigence n'est pas d'injecter des modèles de vue dans la vue ... Nous avons des classes 'espace de travail' qui lient une vue avec un modèle de vue, donc aucune vue n'est consciente de l'instance de modèle de vue attachée. Bien sûr, l'injection peut être faite à partir de l'espace de travail ... J'ai essayé cela et ne semble toujours pas fonctionner.
Mais n'y a-t-il pas d'autre méthode élégante et MVVM-ish pour cela? J'ai préparé un exemple très simple qui illustre mon problème.
J'ai 2 boîtes de saisie, liés à la même propriété dans le modèle de vue:

<StackPanel> 
    <Label>First text box</Label> 
    <TextBox 
     Text="{Binding Path=Property, 
       NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, 
       ValidatesOnDataErrors=True, NotifyOnValidationError=True}" 
    /> 
    <Label>Second text box</Label> 
    <TextBox 
     Text="{Binding Path=Property, 
       NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, 
       ValidatesOnDataErrors=True, NotifyOnValidationError=True}" 
     /> 
</StackPanel> 

Le modèle de vue a la mise en œuvre IDataErrorInfo:

public String this[String propertyName] 
{ 
    get 
    { 
     String error = null; 
     if (propertyName == "Property") 
     { 
      if (Property != "1000") 
      { 
       error ="Only value '1000' is accepted here."; 
       MessageBox.Show(error, "Error", MessageBoxButton.OK, MessageBoxImage.Error); 
       Property = "1000"; 
      } 
     } 
     return error; 

    } 
} 

Dans un premier temps, la valeur est « 1000 ».
Si j'ajoute un "0" dans une zone de texte, le message est affiché, l'autre zone de texte est correctement mise à jour à "1000", mais la valeur de la zone de texte focalisée reste "10000".
Je sens que quelque chose d'essentiel me manque ici.

Lucia

Questions connexes