IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Silverlight Discussion :

Activer/désactiver un bouton avec une action sur une textbox


Sujet :

Silverlight

  1. #1
    Invité
    Invité(e)
    Par défaut Activer/désactiver un bouton avec une action sur une textbox
    Bonjour,
    je rencontre un petit problème sur mon appli Silverlight. La situation est assez simple:
    Une page avec un grille chargant une liste d'Entity (System.ServiceModel.DomainServices.Entity)
    3 boutons (les classiques Création, Edition, Suppression) dont les 2 premiers ouvrent une ChildWindow

    Mon problème est le suivant: comment désactiver le bouton "Valider" des child windows si les conditions ne sont pas présentes?

    Pour le moment j'ai quelques chose dans ce genre:

    XAML
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <TextBox Height="23" HorizontalAlignment="Left" Name="txtNomFonction" Text="{Binding ActiveFonction.Fonction_Libelle, Mode=TwoWay}">
    	<i:Interaction.Triggers>
    		<i:EventTrigger EventName="TextChanged">
    			<cmd:EventToCommand Command="{Binding CanSaveFonctionCommand,Mode=OneWay}" />
    		</i:EventTrigger>
    	</i:Interaction.Triggers>
    </TextBox>
     
    <Button x:Name="OKButton" Content="OK" Click="OKButton_Click" IsEnabled="{Binding EditButtonsEnabled}" Width="75" Height="23" />
    <Button x:Name="CancelButton" Content="Annuler" Click="CancelButton_Click" Width="75" Height="23" />
    ViewModel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public class GererFonctionViewModel : ViewModel
    {
    	public GererFonctionViewModel(IEventAggregator messageBus)
    	{
    		this.messageBus = messageBus;
    		CanSaveFonctionCommand = new DelegateCommand<object>(CheckCanSaveFonction);
    	}
     
    	public ICommand CanSaveFonctionCommand { get; private set; }
     
    	private Boolean editButtonsEnabled;
    	public Boolean EditButtonsEnabled
    	{
    		get { return editButtonsEnabled; }
    		set
    		{
    			editButtonsEnabled = value;
    			OnPropertyChanged("EditButtonsEnabled");
    		}
    	}
     
    	public void CheckCanSaveFonction(object obj)
    	{
    		EditButtonsEnabled = CanSaveFonction();
    	}
     
    	private bool CanSaveFonction()
    	{
    		return ActiveFonction != null && !string.IsNullOrEmpty(ActiveFonction.Fonction_Libelle);
    	}
    }
    Le problème est que lorsque CanSaveFonctionCommand est déclanché par l'Event TextChanged, la propriété de l'objet (ActiveFonction.Fonction_Libelle) n'est pas encore mise à jour lorsqu'on atteint le code de la méthode CanSaveFonction().

    D'où ma question: Comment puis-je faire pour Activé/désactiver ce bouton OK en fonction du résultat de la méthode CheckCanSaveFonction()?

  2. #2
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 080
    Points
    8 080
    Par défaut
    Y'a plus élégant!
    Tout d'abord, il faut créer un behavior pour ton textbox comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    	public class UpdateSourceOnTextChanged : Behavior<TextBox>
    	{
    		protected override void OnAttached()
    		{
    			if (AssociatedObject != null)
    				AssociatedObject.TextChanged += OnTextChanged;
     
    			base.OnAttached();
    		}
     
    		protected override void OnDetaching()
    		{
    			if (AssociatedObject != null)
    				AssociatedObject.TextChanged -= OnTextChanged;
     
    			base.OnDetaching();
    		}
     
    		private void OnTextChanged(object sender, TextChangedEventArgs e)
    		{
    			var bindingExpression = AssociatedObject.GetBindingExpression(TextBox.TextProperty);
    			if (bindingExpression != null)
    				bindingExpression.UpdateSource();
    		}
    	}
    Que tu utilises comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <TextBox Text="{Binding Path=FeedbackContent, Mode=TwoWay}">
    	<i:Interaction.Behaviors>
    		<ui:UpdateSourceOnTextChanged />
    	</i:Interaction.Behaviors>
    </TextBox>
    Ainsi le binding est fait à chaque caractère changé.
    Ensuite, c'est tout simple: le DelegateCommand prend deux méthodes en paramètre, tu peux donc faire un truc comme ca:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    public class FeedbackViewModel : ViewModel
    {
    	private readonly DelegateCommand _submitFeedback;
     
    	private string _feedbackContent;
    	public string FeedbackContent
    	{
    		get { return _feedbackContent; }
    		set
    		{
    			_feedbackContent = value;
    			RaisePropertyChanged(() => FeedbackContent);
    			_submitFeedback.RaiseCanExecuteChanged();
    		}
    	}
    		public ICommand SubmitFeedback { get { return _submitFeedback; } }
     
    	public FeedbackViewModel()
    	{
    		_submitFeedback = new DelegateCommand(SubmitFeedbackExecute, SubmitFeedbackCanExecute);
    	}
     
    	private bool SubmitFeedbackCanExecute()
    	{
    		return !String.IsNullOrWhiteSpace(FeedbackContent);
    	}
     
    	private void SubmitFeedbackExecute()
    	{
    		//mon code ici
    	}
    }

  3. #3
    Invité
    Invité(e)
    Par défaut
    Cette méthode marche très bien sur le contrôle du champs.
    Dès que j'efface le texte requis, le champs texte est mis à jour.


    Par contre quand je bind une ICommand sur le bouton de validation, il reste toujours dans l'état initial.
    Par exemple:
    Si j'ouvre la fenêtre de création, le bouton OK reste grisé après avoir entré du texte.

    Ouverture


    Edition



    Si j'ouvre la fenêtre de création, le bouton OK reste actif après avoir supprimé tout le texte.

    Ouverture


    Edition



    Pour le code j'ai ajouté la behavior dans la textbox et pour le bouton OK j'ai ajouté une ICommand.

    Dans le constructeur du VM
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SaveFonctionCommand = new DelegateCommand<object>(SaveFonction, CanSaveFonction);
    Déclaration de la ICommand
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public ICommand SaveFonctionCommand { get; private set; }
    Ouverture de la fenêtre d'édition
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public void AjouterFonction(object obj)
    {
    	SelectedFonction = new Fonction();
     
    	EditerFonctionChildWindow = new Views.ChildViews.EditerFonction();
    	EditerFonctionChildWindow.OKButton.Command = SaveFonctionCommand;
    	EditerFonctionChildWindow.Show();
    }
    Vérification et sauvegarde de l'objet édité/créé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public bool CanSaveFonction(object obj)
    {
    	return (!string.IsNullOrEmpty(SelectedFonction.Fonction_Libelle));
    }
     
    public void SaveFonction(object obj)
    {
    	if (string.IsNullOrEmpty(SelectedFonction.Fonction_pk.ToString())) domainContext.Fonctions.Add(SelectedFonction);
    	domainContext.SubmitChanges(callback, null);
    }
    Je me trompe où?

  4. #4
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 080
    Points
    8 080
    Par défaut
    Sur le bout la:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public string FeedbackContent
    {
    	get { return _feedbackContent; }
    	set
    	{
    		_feedbackContent = value;
    		RaisePropertyChanged(() => FeedbackContent);
    		_submitFeedback.RaiseCanExecuteChanged();
    	}
    }
    Lorsque tu changes la valeur de la propriété il faut aller dire à la DelegateCommand qu'elle doit notifier l'interface qu'elle doit réexecuter la fonction CanSaveFonction car le résultat est probablement différent.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Ok, ça marche super. Encore merci.

    Par contre, comme mon textbox est directement bindé à un objet (une classe Entity générée par EntityFramework) du contenu dans le view model j'ai du passé par une un propriété "intermédiaire" pour appeler la méthode RaiseCanExecuteChanged() du DelegateCommand.
    Ça me donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [Required()]
    public string Fonction_Libelle
    {
        get { return SelectedFonction.Fonction_Libelle; }
        set
        {
            SelectedFonction.Fonction_Libelle = value;
            SaveFonctionCommand.RaiseCanExecuteChanged();
        }
    }
    Autant pour une fenêtre avec un champs c'est pas un problème, mais si je me retrouve avec 20 champs ça risque de vite devenir lourd de coder tout ça.
    Il n'y aurait pas de manière plus pratique?

    En plus, je n'ai pus le message d'erreur en rouge quand le champ et vide (cf. screenshot dans mon précédent message).
    Dernière modification par Deepin ; 03/08/2011 à 17h17.

  6. #6
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 080
    Points
    8 080
    Par défaut
    Généralement ce que je fais dans ce cas la c'est que pour chaque entité je definis également un viewmodel pour cette entité qui m'encapsule tout ce genre de trucs (validation, notification, etc)

  7. #7
    Invité
    Invité(e)
    Par défaut
    Logique.
    Encore merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [WD18] Metre une colonne d'une Table sur une ligne d'une autre Table
    Par Totophe2 dans le forum WinDev
    Réponses: 2
    Dernier message: 22/11/2013, 12h58
  2. Binder la propriété IsEnabled d'un bouton avec un trigger sur une textbox
    Par Will Fou dans le forum Windows Presentation Foundation
    Réponses: 2
    Dernier message: 04/09/2012, 09h42
  3. Action appelant une action sur une autre application + plus flux xml
    Par Cybero dans le forum Développement Web en Java
    Réponses: 0
    Dernier message: 11/01/2011, 16h05
  4. probleme avec l'appui sur une touche sur une jframe ou jdialog
    Par jeanfeu dans le forum Agents de placement/Fenêtres
    Réponses: 1
    Dernier message: 05/08/2008, 16h14
  5. Demande d'aide sur une action sur un bouton
    Par Kemanke dans le forum MFC
    Réponses: 4
    Dernier message: 29/06/2007, 16h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo