2017-06-15 37 views
-1

我有一个按钮,点击它启动任务并禁用按钮,当任务完成时,我想启用此按钮。请给我任何想法,概念或代码,以便我理解。如何在任务完成时启用WPF中的按钮

我的代码如下:

在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 
    } 
+0

向我们展示'RunTask'的代码。你不应该先禁用按钮**吗? – MickyD

回答

2

这里是一个第一种非常幼稚的方法,没有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) 
} 

如果你有一个长期运行的任务,是不是awaitable,您可以通过Task.Run像这样运行:

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

这是正确的答案,因为他正在使用代码隐藏点击事件。但我同意,还有其他方式通过绑定来实现这一点;主要用于MVVM模式。 –

+0

只是为了说清楚,使用视图模型并不意味着您不能使用async/await。异步RunTask方法也可以驻留在视图模型中。 – Clemens

+0

@clemens thons完成 – Coding4Fun

-1

这里是一个解决方案,在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(); 
    } 
} 
+0

是的,命令是完整的mvvm wpf方法的预期方式。根据实施要求,锁定可能是不必要的,但(可能在使用“await”时) – mcy

+1

您应**等待**您创建的任务。此外,它更好地启用和禁用**主任务线程任务外的按钮**,否则您有可能从错误的线程调用** OnPropertyChanged **。 ** Task.Delay()**对小猫也更好 – MickyD

+0

不,我不应该。如果你喜欢并需要异步方法 - 继续,但他们不是“使用或死亡”的东西。此外,由于绑定使用UI线程的分派器,因此在哪里调用OnPropertyChange没有区别。 –

相关问题