2017-06-15 55 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沒有區別。 –

相關問題