2010-03-11 5 views
1

J'ai un bouton dont j'ai besoin d'être désactivé quand des erreurs de validation se produisent dans ma fenêtre. Les éléments sur lesquels ces erreurs peuvent se produire sont toutes des zones de texte.mettre le bouton datacontext à plusieurs éléments

Je suis lié mon datacontext Button en tant que tel:

DataContext="{Binding ElementName=txtEmail}" 

Maintenant, avec cela, je peux définir le style de bouton pour personnes handicapées lorsque des erreurs de validation se produisent dans la zone de texte de courrier électronique, mais je veux le faire aussi quand cela se produit dans d'autres zones de texte dans ma fenêtre?

Comment puis-je définir cette liaison à plusieurs zones de texte?

Répondre

3

Vous ne pouvez pas, au moins pas directement. Vous pouvez utiliser un MultiBinding avec toutes les zones de texte souhaitées comme entrées, mais vous devrez fournir un IMultiValueConverter aux différentes zones de texte « combiner » dans un objet (par exemple une liste):

<Button> 
    <Button.DataContext> 
    <MultiBinding Converter="{StaticResource ListMaker}"> 
     <Binding ElementName="txtEmail" /> 
     <Binding ElementName="txtFirstName" /> 
     <Binding ElementName="txtLastName" /> 
    </MultiBinding> 
    </Button.DataContext> 
</Button> 

Et est alors cet objet de liste résultant qui sera passé à votre déclencheur, de sorte que vous ne serez pas en mesure d'accéder directement à la propriété Validation.HasError: votre DataTrigger devra également introduire un convertisseur qui convertit l'objet liste en un booléen indiquant si Validation.HasError est défini pour tout ce qui se trouve dans la liste. A ce stade, vous pourriez tout aussi bien oublier les déclencheurs et se lient IsEnabled en utilisant un MultiBinding:

<Button> 
    <Button.IsEnabled> 
    <MultiBinding Converter="{StaticResource AllFalse}"> 
     <Binding Path="(Validation.HasError)" ElementName="txtEmail" /> 
     <Binding Path="(Validation.HasError)" ElementName="txtFirstName" /> 
     <Binding Path="(Validation.HasError)" ElementName="txtLastName" /> 
    </MultiBinding> 
    </Button.DataContext> 
</Button> 

(ici le convertisseur AllFalse retourne true si toutes les entrées sont fausses, et false si une entrée est vraie.)

Une meilleure approche, cependant, peut être que, au lieu de lier directement le bouton à d'autres éléments de l'interface utilisateur, votre objet de données - le même objet que vos zones de texte - affiche une propriété IsValid (avec des notifications de modification appropriées), et liez votre Button.IsEnabled à cela:

<Button IsEnabled="{Binding IsValid}" /> 

Cela vous amène vers une solution de type MVVM qui aide à des choses comme la testabilité (par ex. il est facile de créer des tests pour la propriété IsValid; il est beaucoup plus difficile de créer des tests pour Button.IsEnabled).

+0

Merci beaucoup de me donner les options! J'opterais pour votre dernière option, pourriez-vous élaborer un peu plus sur la façon de s'y prendre? –

+2

L'approche exacte dépendra de la manière dont vous implémentez la validation pour le moment. Supposons que c'est une approche IDataErrorInfo où vous savez quels champs sont actuellement invalides. Ensuite, vous créez simplement une propriété IsValid en lecture seule qui renvoie true si des champs sont actuellement non valides. Et dans chacun de vos setters de propriété, vous augmenteriez PropertyChanged pour la propriété IsValid, de sorte que WPF le re-interrogerait après chaque fois qu'il poussait une liaison à l'objet de données. (Sinon, WPF ne connaîtra pas l'actualisation de la liaison Button.IsEnabled.) Est-ce logique? – itowlson

+0

Type de ... J'utilise IDataErrorInfo. Mais le bit de la propriété dont je suis confus? Qui soulève et qui le gère? Je pense que IsValid devrait augmenter et d'autres gérer? Non? –

0

Pour l'approche MVVM, vous pouvez essayer d'implémenter un routeur de commande à partir de ICommand.

<Button Command="{Binding Path=Commands.MyButtonCommand}" Style="{StaticResource MyButtonStyle}" ></Button> 

où la propriété fait partie des commandes du ViewModel. Vous avez alors le contrôle sur la fonctionnalité que la commande implémente ainsi que si elle est activée ou non. Les tests sont alors beaucoup plus faciles.

Questions connexes