Autres conseils

Je connaissais CommandManager.InvalidateRequerySuggested () il y a longtemps, et l'a utilisé, mais ça ne marchait pas pour moi parfois. J'ai finalement compris pourquoi ce fut le cas! Même si elle ne jette pas comme d'autres actions, vous devez appeler sur le thread principal.

L'appeler sur un thread d'arrière-plan semble fonctionner, mais parfois quitter l'interface utilisateur désactivé. J'espère vraiment que cela aide quelqu'un, et les enregistre les heures que je viens de perdre.

Une solution pour cela lie IsEnabled à une propriété:

<Button Content="Button" Command="{Binding Cmd}" IsEnabled="{Binding Path=IsCommandEnabled}"/>

et puis mettre en œuvre cette propriété dans votre ViewModel. Cela rend également un peu plus facile pour le UnitTesting de travailler avec les propriétés plutôt que des commandes pour voir si la commande peut être exécutée à un certain moment.

Personnellement, je trouve plus pratique.

Probablement cette variante vous convient:

 public interface IRelayCommand : ICommand
{
    void UpdateCanExecuteState();
}

Mise en œuvre:

 public class RelayCommand : IRelayCommand
{
    public event EventHandler CanExecuteChanged;


    readonly Predicate<Object> _canExecute = null;
    readonly Action<Object> _executeAction = null;

   public RelayCommand( Action<object> executeAction,Predicate<Object> canExecute = null)
    {
        _canExecute = canExecute;
        _executeAction = executeAction;
    }


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

    public void UpdateCanExecuteState()
    {
        if (CanExecuteChanged != null)
            CanExecuteChanged(this, new EventArgs());
    }



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

Utilisation simple:

public IRelayCommand EditCommand { get; protected set; }
...
EditCommand = new RelayCommand(EditCommandExecuted, CanEditCommandExecuted);

 protected override bool CanEditCommandExecuted(object obj)
    {
        return SelectedItem != null ;
    }

    protected override void EditCommandExecuted(object obj)
    {
        // Do something
    }

   ...

    public TEntity SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            _selectedItem = value;

            //Refresh can execute
            EditCommand.UpdateCanExecuteState();

            RaisePropertyChanged(() => SelectedItem);
        }
    }

XAML:

<Button Content="Edit" Command="{Binding EditCommand}"/>

Merci les gars pour les conseils. Voici un peu de code sur la façon de maréchal cet appel d'un fil BG au fil de l'interface utilisateur:

private SynchronizationContext syncCtx; // member variable

Dans le constructeur:

syncCtx = SynchronizationContext.Current;

Sur le fil d'arrière-plan, pour déclencher le requery:

syncCtx.Post( delegate { CommandManager.InvalidateRequerySuggested(); }, null );

L'espoir qui aide.

- Michael

Pour mettre à jour un seul GalaSoft.MvvmLight.CommandWpf.RelayCommand vous pouvez utiliser

mycommand.RaiseCanExecuteChanged();

et pour moi, je l'ai créé une méthode d'extension:

public static class ExtensionMethods
    {
        public static void RaiseCanExecuteChangedDispatched(this RelayCommand cmd)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => { cmd.RaiseCanExecuteChanged(); }));
        }

        public static void RaiseCanExecuteChangedDispatched<T>(this RelayCommand<T> cmd)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => { cmd.RaiseCanExecuteChanged(); }));
        }
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top