【问题标题】:C#: Disable button during search/calculationC#:在搜索/计算期间禁用按钮
【发布时间】:2015-09-09 13:15:57
【问题描述】:

我有一个搜索对话框,我想在搜索过程中禁用搜索按钮。这是当前代码,但按钮没有被停用

查看:

<Button Content="Search" 
        Command="{Binding StartSearchCommand}" 
        IsEnabled="{Binding IsNotSearching}" />

视图模型:

private bool _isNotSearching;
public bool IsNotSearching
{
    get { return _isNotSearching; }
    set
    {
        _isNotSearching = value;
        OnPropertyChanged("IsNotSearching");
    }
}


private RelayCommand<object> _startSearchCommand;
public ICommand StartSearchCommand
{
    get
    {
        if (_startSearchCommand == null)
            _startSearchCommand = new RelayCommand<object>(p => ExecuteSearch());
        return _startSearchCommand;
    }
}
private void ExecuteSearch()
{
    IsNotSearching = false;
    //do some searching here
    IsNotSearching = true;
}

【问题讨论】:

  • 那是因为你通过执行 Thread.Sleep 阻塞了 UI 线程。如果您要在后台线程中执行某些任务,那么一切都应该按您的预期工作
  • 试过了。让它有事可做。但是该按钮在执行时看起来被点击了并且没有被停用
  • 它正在发生,但速度如此之快,你看不到它。 ExecuteSearch() 在完成之前不会更新 UI,因此 IsNotSearching = false 和 IsNotSearching = true 同时发生。
  • @Frisbee:我计算了一些需要很长时间的东西。我可以看到它被点击了,它完成了
  • @juergend 所以你可以看到它被点击了。这证明了什么?

标签: c# wpf mvvm


【解决方案1】:

出于这个原因,我创建了一个AsyncDelegateCommand(基于著名的DelegateCommand),它在执行命令操作期间在内部禁用命令(在 UI 中):

public class AsyncDelegateCommand : ICommand
{
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;
    bool _running;

    public event EventHandler CanExecuteChanged;

    public AsyncDelegateCommand(Action<object> execute, Predicate<object> canExecute = null)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return (_canExecute == null ? true : _canExecute(parameter)) && !_running;
    }

    public async void Execute(object parameter)
    {
        _running = true;
        Update();
        await Task.Run(() => _execute(parameter));
        _running = false;
        Update();
    }

    public void Update()
    {
        if (CanExecuteChanged != null)
            CanExecuteChanged(this, EventArgs.Empty);
    }
}

xaml:

<Button Command="{Binding SomeCommand}" .../>

视图模型:

AsyncDelegateCommand SomeCommand { get; }

    // in constructor
    SomeCommand = new AsyncDelegateCommand(o =>  { Thread.Sleep(5000); }); // code to run

【讨论】:

    【解决方案2】:

    我不确定单击和禁用它时的外观 - 它可能看起来相同。

    但是netaholic 是对的。如果您在主 UI 线程中执行逻辑,则 UI 可能会冻结到您的执行结束(并且不会更改或更改为快速)。

    尝试将您的逻辑放入dispatcher。就像代码的下一部分一样。

    Application.Current.Dispatcher.BeginInvoke(
      DispatcherPriority.Background,
      new Action(() => { 
        //do some searching here
      }));
    

    顺便说一句,我拿了这个代码there

    编辑:不要将它用于您的解决方案。这是错误的(检查 cmets)。

    当您需要异步更新视觉元素时使用调度程序。

    Application.Current.Dispatcher.BeginInvoke(
          DispatcherPriority.Background,
          new Action(() => { 
            textbox.Content = "some result";
          }));
    

    【讨论】:

    • Application Dispatcher 在 UI 线程上执行委托。这也会冻结应用程序。
    【解决方案3】:

    您可以尝试命令可以执行以禁用该命令而不添加IsEnabled属性

    private RelayCommand _startSearchCommand;
        public RelayCommand StartSearchCommand
        {
            get
            {
                return _startSearchCommand??
                       (_startSearchCommand=
                    //Added can execute command , only execute if system is not busy at the moment.
                           new RelayCommand(async () => await OnExecuteSearch(), () => !IsBusy));
            }
    
        }
    

    命令处理程序

    internal async Task OnExecuteSearch()
        {
            IsBusy = true;
    
            //Execute your action
            //and finally
            IsBusy = false;
    
        }
    

    Xaml

     <Button Command="{Binding StartSearchCommand}">
    

    中继命令中的canexecute 将为您控制IsEnabled 属性。

    【讨论】:

      【解决方案4】:

      此代码必须有效。

      private async void ExecuteSearch() {
              IsNotSearching = false;
      
              var task = Task.Factory.StartNew(() => {
                  //do some searching here
              });
              await task;
      
              IsNotSearching = true;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-05
        • 1970-01-01
        • 2011-01-13
        相关资源
        最近更新 更多