74

CanExecuteカスタム コマンド (Josh Smith の) で強制的に呼び出す方法を知っている人はいますRelayCommandか?

通常、CanExecuteUI で対話が発生するたびに呼び出されます。何かをクリックすると、コマンドが更新されます。

CanExecute舞台裏でタイマーによって条件がオン/オフされている状況があります。これはユーザーの操作によって駆動されないためCanExecute、ユーザーが UI を操作するまで呼び出されません。最終結果はButton、ユーザーがクリックするまで有効/無効のままです。クリック後、正しく更新されます。が有効に表示されることがありButtonますが、ユーザーがクリックすると、起動する代わりに無効に変わります。

タイマーが影響するプロパティを変更したときに、コードで強制的に更新するにはどうすればよいCanExecuteですか? に影響するプロパティでPropertyChanged( ) を起動しようとしましたが、効果はありませんでした。INotifyPropertyChangedCanExecute

XAML の例:

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

コードビハインドの例:

private ICommand m_cmd;
public ICommand Cmd
{
    if (m_cmd == null)
        m_cmd = new RelayCommand(
            (param) => Process(),
            (param) => EnableButton);

    return m_cmd;
}

// Gets updated from a timer (not direct user interaction)
public bool EnableButton { get; set; }
4

6 に答える 6

104

呼び出しSystem.Windows.Input.CommandManager.InvalidateRequerySuggested()により、CommandManager は強制的に RequerySuggested イベントを発生させます。

備考: CommandManager は、キーボード フォーカスの変更など、コマンド ターゲットがいつ変更されたかを判断する際に、特定の条件にのみ注意を払います。CommandManager が、コマンドを実行できない原因となる条件の変化を十分に判断できない状況では、InvalidateRequerySuggested を呼び出して、CommandManager に RequerySuggested イベントを強制的に発生させることができます。

于 2009-04-23T19:08:44.070 に答える
29

CommandManager.InvalidateRequerySuggested() はずっと前に知っていて使用していましたが、うまくいかないことがありました。なぜこうなったのか、やっとわかりました!他のアクションのようにスローされませんが、メイン スレッドで呼び出す必要があります。

バックグラウンド スレッドで呼び出しても機能しているように見えますが、UI が無効になっている場合があります。これが誰かを助け、私が無駄にした時間を節約できることを本当に願っています.

于 2010-02-23T15:30:01.500 に答える
17

IsEnabledその回避策は、プロパティにバインドすることです。

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

次に、このプロパティをViewModelに実装します。これにより、UnitTestingがコマンドではなくプロパティを操作して、特定の時点でコマンドを実行できるかどうかを確認するのも少し簡単になります。

個人的にはもっと便利だと思います。

于 2012-05-04T08:10:46.070 に答える
6

おそらく、この変種はあなたに合っています:

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

実装:

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

シンプルな使用:

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}"/>
于 2012-12-05T08:58:56.197 に答える
4

ヒントをありがとう。BG スレッドから UI スレッドへの呼び出しをマーシャリングする方法に関するコードを次に示します。

private SynchronizationContext syncCtx; // member variable

コンストラクターで:

syncCtx = SynchronizationContext.Current;

バックグラウンド スレッドで、再クエリをトリガーするには:

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

それが役立つことを願っています。

-- マイケル

于 2011-03-03T19:45:57.393 に答える