質問
誰もが、私はカスタムコマンドで呼び出さ取得するCanExecute
を強制することができる方法を知っています(ジョシュ・スミスの<のhref =「http://msdn.microsoft.com/en-us/magazine/dd419663.aspx」のrel = "noreferrer 「> RelayCommand
の)?
の相互作用がUIに発生するたびに通常、CanExecute
が呼び出されます。私は何かをクリックした場合、私のコマンドが更新されます。
私はCanExecute
のための条件は舞台裏タイマーによってオン/オフになっている状況があります。これは、ユーザとの対話によって駆動されていないので、ユーザはUIと対話するまで、CanExecute
は呼び出されません。最終結果は、ユーザーがそれをクリックするまで、私のButton
が無効/有効のままということです。クリックした後、それが正しく更新されます。時にはButton
が有効になって表示されますが、ユーザーがクリックしたときではなく、発射のdisabledに変更します。
CanExecute
に影響プロパティを変更したときどのように私はコード内の更新を強制することができますか?私はPropertyChanged
に影響性質上INotifyPropertyChanged
(CanExecute
)を発射しようとしたが、それは助けにはならなかった。
例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; }
他のヒント
私は長い時間前にCommandManager.InvalidateRequerySuggested()を知っていたし、それを使用しますが、それは時々私のために働いていませんでした。このようなケースだった、なぜ私は最終的に考え出しました!それはいくつかの他のアクションのようにスローしませんが、あなたは、メインスレッド上で、それを呼び出す必要があります。
バックグラウンドスレッドでそれを呼び出すと、動作しているように見えますが、時々無効にUIを残します。私は本当にこれが誰かを助け、そして彼らに私は無駄な時間を節約できます願っています。
それを回避するには、プロパティにIsEnabled
結合されます。
<Button Content="Button" Command="{Binding Cmd}" IsEnabled="{Binding Path=IsCommandEnabled}"/>
、その後、あなたのViewModelでこのプロパティを実装します。また、これは、それが少し簡単に単体テストコマンドは、特定の時点で実行することが可能かどうかを確認するためのプロパティではなく、コマンドで作業できるようになります。
私は、個人的に、それがより便利に見つけます。
おそらくこのバリアントは、あなたに合うでしょう。
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}"/>
のヒントのためのみんなありがとう。ここではBGスレッドからUIスレッドにその呼び出しをマーシャリングする方法については、コードのビットがあります:
private SynchronizationContext syncCtx; // member variable
コンストラクタでます:
syncCtx = SynchronizationContext.Current;
バックグラウンドスレッドで、再クエリをトリガする
syncCtx.Post( delegate { CommandManager.InvalidateRequerySuggested(); }, null );
希望に役立ちます。
- マイケル
一つだけGalaSoft.MvvmLight.CommandWpf.RelayCommandを更新するには、あなたが使用することができます。
mycommand.RaiseCanExecuteChanged();
と私のために私は拡張メソッドを作成しました。
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(); }));
}
}