长时间操作时禁用按钮
本文关键字:按钮 操作 长时间 | 更新日期: 2023-09-27 18:11:23
在长时间操作期间,我想禁用按钮并清除文本块。
On button click事件在绘制屏幕之前被完全处理,因此按钮永远不会被明显禁用
private bool btnEnabled = true;
public bool BtnEnabled
{
get { return btnEnabled; }
set
{
if (value == btnEnabled)
return;
btnEnabled = value;
NotifyPropertyChanged("BtnEnabled");
}
}
private string results = "start";
public string Results
{
get { return results; }
set
{
if (value == results)
return;
results = value;
NotifyPropertyChanged("Results");
}
}
private void btn_Click(object sender, RoutedEventArgs e)
{
BtnEnabled = false;
Results = string.Empty;
// whould like to displany wait spinner
LongProcess();
BtnEnabled = true;
}
private void LongProcess()
{
//database query
System.Threading.Thread.Sleep(10000);
Results = "this is the results";
}
如何使按钮在长事件期间禁用?
我遇到的问题是用户感到沮丧,开始点击,这些点击都在队列中,并得到处理。
要回答您的特定问题,您可以使用以下代码让UI处理消息(在将按钮设置为禁用之后):
Application.Current.Dispatcher.Invoke(
DispatcherPriority.Background,
new Action(delegate { })
);
或者更完整的:
public void DoEvents()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(ExitFrame), frame);
Dispatcher.PushFrame(frame);
}
public object ExitFrame(object f)
{
((DispatcherFrame)f).Continue = false;
return null;
}
然后,不建议使用(它相当于在Winforms上使用Application.DoEvents()
,它有许多警告,应该像瘟疫一样避免,除非您知道自己在做什么)。长时间密集的操作不应该在UI线程上完成,或者如果它们不是CPU密集的,您可以使用async/await
。
这就是我最后的结果
private async void btn_Click(object sender, RoutedEventArgs e)
{
BtnEnabled = false;
Results = string.Empty;
// whould like to displany wait spinner
//LongProcess();
cts = new CancellationTokenSource();
try
{
//cts.Cancel(); just for test
string result = await WaitAsynchronouslyAsync(cts.Token);
//string result = await WaitSynchronously();
BtnEnabled = true;
Results = result;
}
catch (OperationCanceledException)
{
Results = "Operation canceled"; // this is not called
}
cts = null;
}
// The following method runs asynchronously. The UI thread is not
// blocked during the delay. You can move or resize the Form1 window
// while Task.Delay is running.
public async Task<string> WaitAsynchronouslyAsync(CancellationToken ct)
{
//DataBaseQuery(); // this just runs async
//SqlCommand cmd = new SqlCommand();
//await cmd.ExecuteScalarAsync(ct);
await Task.Delay(10000);
return "Finished";
}