Andere Tipps

Ich war bewusst CommandManager.InvalidateRequerySuggested () vor langer Zeit, und verwenden es, aber es funktioniert nicht manchmal für mich. Ich endlich herausgefunden, warum dies der Fall war! Auch wenn es wie einige andere Aktionen nicht werfen, haben Sie es auf dem Hauptthread zu nennen.

es auf einem Hintergrund-Thread aufrufen erscheint, zu arbeiten, aber manchmal die Benutzeroberfläche deaktiviert lassen. Ich hoffe wirklich, dass dies jemand hilft, und speichert sie die Stunden, die ich nur verschwendet.

Eine Abhilfe für das verbindlich IsEnabled auf eine Eigenschaft:

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

und dann diese Eigenschaft in Ihrem Ansichtsmodell implementieren. Dies macht es auch ein bisschen einfacher für den Unittesting mit den Eigenschaften zu arbeiten, anstatt Befehlen zu sehen, ob der Befehl zu einem bestimmten Zeitpunkt ausgeführt werden kann.

Ich persönlich finde es bequemer.

Wahrscheinlich wird diese Variante zu Ihnen passen:

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

Umsetzung:

 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();
    }
}

einfache Verwendung:

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}"/>

Danke Jungs für die Tipps. Hier ist ein Stück Code wie dieser Anruf Marschall von einem BG Thread zu dem UI-Thread:

private SynchronizationContext syncCtx; // member variable

Im Konstruktor:

syncCtx = SynchronizationContext.Current;

Auf dem Hintergrund-Thread, die requery auslösen:

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

Ich hoffe, das hilft.

- Michael

Um nur einen einzigen GalaSoft.MvvmLight.CommandWpf.RelayCommand aktualisieren könnten Sie

mycommand.RaiseCanExecuteChanged();

und für mich ich habe eine Erweiterungsmethode erstellt:

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(); }));
        }
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top