有谁知道我怎么能强迫CanExecute得到叫上一个自定义命令(约什 - 史密斯的的 RelayCommand )?

典型地,每当相互作用在UI上发生CanExecute被调用。如果我点击的东西,我的命令被更新。

我有其中用于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; }
有帮助吗?

其他提示

我知道CommandManager.InvalidateRequerySuggested的()很久以前,并用它,但它不是有时为我工作。我终于想通了,为什么是这种情况!即使它不会引发像其他一些动作,你必须把它在主线程上。

调用它在后台线程会出现工作,但有时会离开禁用UI。我真的希望这可以帮助别人,并保存他们,我只是浪费了时间。

一个用于该替代方法结合IsEnabled到一个属性:

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

,然后实现在您的视图模型此属性。这也使得更容易一点为单元测试与属性而不是命令的工作,看该命令是否可以在特定的时间点被执行。

我个人觉得它更方便。

也许这变种会适合你:

 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(); }));
        }
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top