我正在开发一个遵循 MVVM 设计模式的 WPF 应用程序。对于线程,我打算使用 Backgroundworker。从视图模型中,我需要启动线程以执行耗时操作。请建议我如何在线程执行之前显示等待对话框。如果可能,请提供示例代码。问候, 阿尼尔班
3 回答
您可以向 ViewModel 添加一个属性,指示后台工作程序(或其他异步操作)正忙。
视图可以绑定到此属性以显示进度条或其他忙碌指示符。
只需确保正确设置和重置属性即可。
编辑
请参阅此问题/答案以在 WPF 中制作模式对话框:如何在 WPF 中制作模式对话框?
作为替代方案,您可以使用此设置(伪代码):
<Window>
<Grid>
<Grid x:Name="regularContent">
</Grid>
<Grid x:Name="Overlay" Visibility="Collapsed">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Progressbar Value="{Binding Path=Progress}" />
</StackPanel>
</Grid>
</Grid>
</Window>
后面的代码:
private void ShowPopup()
{
RegularContent.IsEnabled = false;
Overlay.Visibility = Visibility.Visible;
}
private void ClosePopup()
{
RegularContent.IsEnabled = true;
Overlay.Visibility = Visibility.Collapsed;
}
确保禁用常规内容以防止用户使用标签。
您可以使用相同的结构来屏蔽视图的一部分,而不是像我所做的那样完全屏蔽它。
应该在 UI 线程上修改 ProgressBar 绑定到的 ViewModel 上的 Progress 属性。如果您正在使用将自动完成的后台工作程序,因为在 UI 线程上引发了 ReportProgress 事件。
如果您使用不同的方式创建工作线程,请确保您使用调度程序来更新 Progress 属性。
我在 Windows Phone 中使用它:
private readonly BackgroundWorker worker = new BackgroundWorker();
private PerformanceProgressBar loader = new PerformanceProgressBar();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
bar.IsIndeterminate = true;
Bar.Enabled = true;
}
private void worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
bar.Enabled = false;
}
worker.RunWorkerAsync();
如果要定义一个 MVVM 结构: PerformanceProgressBar "Invalid cross-thread access" 异常
当然,类似的用户控件也存在于 WPF 中:http ://wpftoolkit.codeplex.com/wikipage?title=Extended%20WPF%20Toolkit%20Controls
最简单的方法是使用 wpf busyindicator ( http://elegantcode.com/2011/10/07/extended-wpf-toolkitusing-the-busyindicator/ )。
您可以将它绑定到模型模型中的一些 thread_is_busy_flag_property(我更喜欢通过定位器模式通过应用程序范围的资源访问的一些单音 - 它很容易在 xaml 和模型视图/代码后面共享)。
设置此标志时不要忘记线程安全(或者您可以使用AutoResetEvent/ManualResetEvent来捕获后台操作结束)。我建议使用 TPL 和任务(更强大的方式)而不是 BackgroundWorker/QueueUserWorkItem。