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

Comprendre le Binding en WPF et Silverlight


précédentsommairesuivant

VII. Les commandes

Jusqu'à présent, nous avons utilisé lors de clics sur des boutons, des gestionnaires d'évènements comme en Winform et ASP.Net. Des nouveautés ont été introduites sur Silverlight/WPF de ce côté. En effet, désormais il est préférable de ne plus utiliser les gestionnaires d'évènements pour les boutons, mais plutôt de « binder » une commande à la propriété Command de Button.
Mais qu'est-ce qu'une commande ? Une commande est une instance d'une classe implémentant ICommand. Bien souvent, dans les frameworks courants, on retrouve une implémentation assez similaire à celle que nous allons voir ici.
ICommand se compose de deux méthodes Execute et CanExecute, la première contient le traitement qui doit se produire lors du déclenchement et la seconde permet de faire un test pour savoir si le traitement peut se dérouler. Il y a également un évènement qui permet de notifier aux abonnés de la commande si le contexte a changé de telle manière qu'un appel à CanExecute ne retourne pas le même résultat qu'avant (exemple : suite à une manipulation utilisateur le test de sécurité qui était faux, devient vrai et l'utilisateur peut ainsi être autorisé à cliquer).
Afin d'avoir quelque chose d'assez générique, voici une proposition d'implémentation :

 
Sélectionnez
public class CommandImpl : ICommand
{
    private readonly Action<object> _execute;
    private readonly Func<object, bool> _canExecute;

    public CommandImpl(Action<object> execute)
        : this(execute, null)
    { }

    public CommandImpl(Action<object> execute, Func<object, bool> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public void Execute(object parameter)
    {
        if (_execute != null)
            _execute(parameter);
    }

    public bool CanExecute(object parameter)
    {
        if (_canExecute != null)
            return _canExecute(parameter);
        else
            return true;
    }

    public event EventHandler CanExecuteChanged;

    public void RequerySuggested()
    {
        if (CanExecuteChanged != null)
            CanExecuteChanged(this, EventArgs.Empty);
    }
}

Cette proposition contient deux constructeurs, le premier précise uniquement l'action à mener (à utiliser quand il n'y a pas de restrictions sur l'utilisation du bouton) et le second précise également les conditions d'exécution.
L'utilisation est la suivante :

 
Sélectionnez
<Grid x:Name="LayoutRoot"
      Margin="5">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
    <TextBox Text="{Binding Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    <Button Grid.Column="1"
            Width="50"
            Content="Submit"
            Command="{Binding Path=MyCommand}" />
</Grid>
 
Sélectionnez
public partial class MainWindow : INotifyPropertyChanged
{
    private String _value;
    public String Value
    {
        get
        {
            return _value;
        }
        set
        {
            _value = value;
            RaisePropertyChanged("Value");
            MyCommand.RequerySuggested();
        }
    }

    public CommandImpl MyCommand { get; private set; }

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        MyCommand = new CommandImpl(MyCommandExecute, MyCommandCanExecute);
    }

    private void MyCommandExecute(object o)
    {
        MessageBox.Show("Hello world!");
    }
    
    private bool MyCommandCanExecute(object o)
    {
         return !String.IsNullOrWhiteSpace(Value);
    }

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion

}

Ici, pour le traitement (Execute), on spécifie la méthode à appeler, mais cela pourrait aussi être une fonction anonyme (un délégué Action<object>). Ce traitement affiche une MessageBox. De la même manière on utilise une fonction qui retourne un booléen afin de vérifier que la propriété Value est bien remplie (on pourrait également se servir d'une fonction anonyme Func<object,bool>). Comme ma commande dépend de la propriété Value, la méthode RequerySuggested de la commande est appelée dans le setter de la propriété. Ainsi, dès que Value change, la condition est réévaluée. Lors du test de ce code, on s'aperçoit qu'on vient d'implémenter d'une façon élégante un contrôle de saisie.


précédentsommairesuivant

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2012 Nathanael Marchand. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.