1
votes

C # WPF intégré à l'interface ICommand et au modèle de conception de commande

Je suis nouveau dans WPF et c # en général. J'étais en train de lire à propos du modèle de conception de commande et j'avais hâte de l'implémenter sur ma nouvelle application afin qu'elle puisse avoir des fonctionnalités faire et annuler. Puis j'ai réalisé que WPF était déjà livré avec une interface ICommand et que les boutons de xml pouvaient l'implémenter. Cette interface a les méthodes suivantes:

public bool CanExecute(object parameter)
{
}

private void OnCanExecuteChanged()
{
}

public void Execute(object parameter)
{
}

Alors, devrais-je ajouter la fonctionnalité d'annulation à cette interface déjà intégrée à ICommand en ayant une autre interface en hérite et en ajoutant la méthode d'annulation?

Cette interface est-elle réservée aux boutons? Je veux dire, j'aimerais créer beaucoup d'autres commandes qui ne sont pas nécessairement connectées à un bouton xnml

merci d'avance!


0 commentaires

4 Réponses :


0
votes
  1. le CanExecute vous mènera à savoir si faire la commande ou non, pour la mise en œuvre de la commande, vous pouvez voir ici .
  2. Votre liaison de commande à Button est obligatoire pour cliquer sur le contrôle Button. Donc, toutes les liaisons "Commande", pas de limite au clic, vérifient également, déposent, se concentrent, etc. fonctionnent

0 commentaires

1
votes

Tout d'abord, les commandes font partie du modèle MVVM et vous devriez d'abord lire à ce sujet.

Les interfaces en C # ne fournissent aucune fonctionnalité, elles décrivent seulement comment la classe qui hérite de cette interface devrait fonctionner. Si vous voulez que la classe fasse quelque chose, vous ne devez pas laisser ces méthodes vides.

Les commandes de WPF représentent une sorte de cadre auquel la logique sera transmise plus tard. L'utilisation la plus logique des commandes est de les lier à des boutons.

Exemple d'implémentation d'ICommand:

        public RelayCommand CancelCommand => NavigationCommands.NavigateBack;

Commande utilisant l'exemple:

<Button x:Name="CancelButton"
            Content="Cancel"
            Command="{Binding CancelCommand}"
            Grid.Row="2"
            IsCancel="True"
            HorizontalAlignment="Left"
            Margin="44,0,0,0"
            Width="118" Height="23"
            VerticalAlignment="Center" />

Exemple de liaison de commande: Dans View (xaml):

 public static RelayCommand NavigateToSignInPage => new RelayCommand(
        actionParameter => Application.Instance.Navigation.NavigateTo(new LoginForm()));

    public static RelayCommand NavigateToSignUpPage => new RelayCommand(
        actionParameter => Application.Instance.Navigation.NavigateTo(new RegistrationForm()));

    public static RelayCommand NavigateToStartPage => new RelayCommand(
        actionParameter => Application.Instance.Navigation.NavigateTo(new StartPage()));

    public static RelayCommand NavigateBack => new RelayCommand(
        actionParameter => Application.Instance.Navigation.NavigateBack(),
        actionPossibilityParameter => Application.Instance.Navigation.BackNavigationPossible);

Dans ViewModel:

public class RelayCommand : ICommand
{
    private readonly Action<object>     execute;
    private readonly Func<object, bool> canExecute;

    public event EventHandler CanExecuteChanged {
        add => CommandManager.RequerySuggested    += value;
        remove => CommandManager.RequerySuggested -= value;
    }

    public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        this.execute    = execute;
        this.canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return canExecute == null || canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        execute(parameter);
    }
}


0 commentaires

0
votes

Je pense que vous confondez les choses ici. Le L'interface ICommand est un élément utilisé pour lier les événements de l'interface utilisateur au code utilisé dans les modèles de conception tels que MVVM . Le Command Design Pattern que vous essayez d'implémenter est une architecture d'état pour annulation d'actions comme une pression sur un bouton.


2 commentaires

Donc, je ferais mieux de créer ma propre interface ICustomCommand pour implémenter la fonctionnalité do-undo. Droit?


Oui, ce serait quelque chose à faire de manière supplémentaire si vous choisissez d'utiliser MVVM, ce que je ne pense pas car c'est un modèle de conception quelque peu complexe. Ce que vous voulez faire est assez bien décrit ici: comment utiliser le modèle de commande pour annuler



0
votes

De nombreuses réponses mettent en évidence une implémentation utile de l'interface ICommand utilisant des délégués. Vous pouvez même aller plus loin en liant les modifications de modèle comme indiqué ci-dessous ou filtrer arbitrairement si vous le souhaitez. Cela peut être utile pour réévaluer si une commande doit être en mesure de se déclencher en fonction de l'état du modèle, car cela est directement lié à l'état "Activé" d'un bouton.

public class Memento<T>
{
    public Memento(T startState)
    {
        this.State = startState;
        this.OriginalState = startState;
    }

    public T State { get; set; }

    public T OriginalState { get; }

    public void RestorOriginalState()
    {
        State = OriginalState;
    }
}

Concernant votre question pour les opérations d'annulation. Vous pouvez certainement utiliser une commande pour l'invoquer, mais garder une trace de l'état de vos objets est la partie la plus délicate. Vous pouvez utiliser le modèle de conception memento et lier votre commande à la fonctionnalité de restauration de l'état. Ceci est une simplification excessive, mais a été au cœur des implémentations que j'ai faites dans le passé.

public class ObservableCommand<T> : ICommand where T : System.ComponentModel.INotifyPropertyChanged
{
    Predicate<object> _predicate;
    Action<object> _execute;
    public ObservableCommand(T model, Action<object> execute, Predicate<object> predicate)
    {
        model.PropertyChanged += ModelChanged;
        _execute = execute;
        _predicate = predicate;
    }

    public event EventHandler CanExecuteChanged;

    private void ModelChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }

    public bool CanExecute(object parameter)
    {
        return _predicate(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }
} 


0 commentaires