【问题标题】:How to enable button in WPF when task is done任务完成后如何在WPF中启用按钮
【发布时间】:2017-06-15 02:32:52
【问题描述】:

我有一个按钮,点击它可以启动一个任务并禁用该按钮,当任务完成后,我想启用这个按钮。请给我任何想法、概念或代码,以便我理解。

我的代码如下:

在 xaml 中:

<Button Name="myButton" Content="START" Click="ButtonStartClick" />

在 xaml.cs 中:

 private void ButtonStartClick(object sender, RoutedEventArgs e)
 {
     RunTask();
     myButton.IsEnabled = false;
 }

在 viewModel.cs 中:

     private void OnTaskCompleted(string result)
     {
          //how to enable myButton
     }

【问题讨论】:

  • 向我们展示RunTask 的代码。您不应该禁用 prior 按钮吗?

标签: c# wpf xaml


【解决方案1】:

这是第一个非常幼稚的方法,没有 MVVM

 private async void ButtonStartClick(object sender, RoutedEventArgs e)
 {
     myButton.IsEnabled = false;
     await RunTask();
     myButton.IsEnabled = true;
 }

其中 RunTask 声明如下:

 private async Task RunTask()
 {
     // await some other awaitable method(s)
 }

如果您有一个无法等待的长时间运行的任务,您可以通过Task.Run 运行它,如下所示:

private async Task RunTask()
{
    await Task.Run(() =>
    {
        // do somthing here
    });
}

【讨论】:

  • 这是正确的答案,因为他正在为点击事件使用代码。但我同意,还有其他方法可以通过绑定来实现这一点;主要用于 MVVM 模式。
  • 明确一点,使用视图模型并不意味着不能使用 async/await。异步 RunTask 方法也可以驻留在视图模型中。
  • @clemens 完成任务
  • @MichaelPuckettII 是的,答案很好,只使用后面的代码
【解决方案2】:

这是 MVVM 风格的解决方案。 MainWindowViewModel.IsButtonEnabled 定义用户是否可以单击按钮。 ICommand.CanExecute 定义是否在单击时触发命令。

Window.xaml:

<Window>
    <Grid>
        <Button Content="Click me!" Command="{Binding ButtonCmd}" IsEnabled="{Binding IsButtonEnabled}" Width="100" Height="30"/>
    </Grid> 
</Window>

Window.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainWindowViewModel(); 
    }
}

ViewModel.cs

class MainWindowViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private bool _isButtonEnabled = true;
    private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();

    public MainWindowViewModel()
    {
        ButtonCmd = new Command(OnButtonClick, () => IsButtonEnabled);
    }

    public ICommand ButtonCmd { get; private set; }

    public bool IsButtonEnabled
    {
        get
        {
            _lock.EnterReadLock();
            bool result = _isButtonEnabled;
            _lock.ExitReadLock();
            return result;
        }
        set
        {
            _lock.EnterWriteLock();
            _isButtonEnabled = value;
            _lock.ExitWriteLock();
            OnPropertychanged(nameof(IsButtonEnabled));
        }
    }        

    private void OnButtonClick()
    {
        Task.Factory.StartNew(()=>{
            IsButtonEnabled = false;
            Thread.Sleep(1000);
            IsButtonEnabled = true;
        });
    }       
    private void OnPropertychanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

Command.cs

class Command : ICommand
{
    public event EventHandler CanExecuteChanged;
    Action _cmd;
    Func<bool> _canExecute;


    public Command(Action cmd, Func<bool> canExecute)
    {
        _cmd = cmd;
        _canExecute = canExecute;
    }
    public bool CanExecute(object parameter)
    {
        return _canExecute();
    }

    public void Execute(object parameter)
    {
        _cmd();
    }
}

【讨论】:

  • 是的,命令是完整 mvvm wpf 方法的预期方式。根据实现要求,锁定可能是不必要的(可能在使用await 左右时)
  • 您应该等待您创建的任务。此外,最好在主 Ui 线程中启用和禁用任务 outside 按钮,否则您将面临从错误线程调用 OnPropertyChanged 的风险。 Task.Delay() 对小猫也更好
  • 不,我不应该。如果您喜欢并需要异步方法 - 继续,但它们不是“使用或死亡”的东西。在哪里调用 OnPropertyChange 也没有区别,因为绑定使用 UI 线程的 Dispatcher。
  • 那好吧。 -1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-23
  • 1970-01-01
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
  • 1970-01-01
  • 2013-05-01
相关资源
最近更新 更多