我正在Visual Studio 2015中构建一个MVVM Light WPF应用程序。它具有一个用户控件,其中包含一个 WindowsFormsHost
,其中包含用于SQL Server报告服务服务本地报告的ReportViewer
。ReportView.xaml
中的一个按钮调用命令,该按钮又将消息发送到MasterListView.xaml
的代码 - 生成报告。
这是ReportViewModel.cs
中的按钮调用的命令:
public ICommand RunReportRelayCommand =>
new RelayCommand(async ()=> { await RunReport(); });
private async Task RunReport()
{
try
{
IsBusy = true;
await Task.Run(() =>
{
Messenger.Default.Send(true, "RunMasterListReport");
});
}
finally
{
IsBusy = false;
}
}
这是ReportViewModel.cs
中IsBusy
属性的定义:
private bool _isBusy;
public bool IsBusy
{
get { return _isBusy; }
set
{
if (value == _isBusy) return;
_isBusy = value;
RaisePropertyChanged();
}
}
相同的视图,包含"调用"按钮的ReportView.xaml
还包含以下扩展的WPF工具包忙指示器:
<UserControl>
<UserControl.Resources>
<DataTemplate x:Key="MasterListViewTemplate">
<view:MasterListView />
</DataTemplate>
</UserControl.Resources>
<xctk:BusyIndicator IsBusy="{Binding IsBusy}">
<StackPanel>
<!-- Other XAML here -->
<ContentControl ContentTemplate="{StaticResource MasterListViewTemplate}" />
</StackPanel>
</xctk:BusyIndicator>
</UserControl>
然后在 MasterListView.cs
代码范围内,我们有:
public partial class MasterListView : UserControl
{
public MasterListView()
{
InitializeComponent();
Messenger.Default.Register<bool>(this, "RunMasterListReport", RunMasterListReport);
}
public async void RunMasterListReport(bool val)
{
await Task.Run(() =>
{
var dataSet = new DrugComplianceDataSet();
dataSet.BeginInit();
ReportViewer.ProcessingMode = ProcessingMode.Local;
ReportViewer.LocalReport.ShowDetailedSubreportMessages = true;
ReportViewer.LocalReport.DataSources.Clear();
var dataSource = new ReportDataSource
{
Name = "MasterListRandomDataSet",
Value = dataSet.MasterListRandom
};
ReportViewer.LocalReport.DataSources.Add(dataSource);
ReportViewer.LocalReport.ReportEmbeddedResource = "MasterListRandom.rdlc";
dataSet.EndInit();
var adapter = new MasterListRandomTableAdapter { ClearBeforeFill = true }
.Fill(dataSet.MasterListRandom);
Dispatcher.Invoke((MethodInvoker)(() => { ReportViewer.RefreshReport(); }));
});
}
}
但是,尽管报告确实在5秒钟左右后显示,但繁忙的指示器并没有触发。我究竟做错了什么?谢谢。
您在那里得到了一整汤。
之类的东西await Task.Run(() =>
建议您不太了解异步/等待如何工作。我会下台,找到一些不错的文档要阅读。另外,您似乎正在在UI线程上完成所有工作。
Dispatcher.Invoke((MethodInvoker)(() => { ReportViewer.RefreshReport(); }));
除非您更新UI,否则您不应在后台工作人员中触摸调度员。看来您正在卸载您打算在UI线程上的背景线程(刷新报告)中要做的实际工作。
也许您的报告查看器必须在UI线程中运行。如果是这样(也许是在一段时间之前设计的,并且没有利用多任务处理),那么您对这种情况无能为力。您的UI在处理时将被锁定。
如果您的所有长期工作都必须在UI线程上运行,请剥离所有这些废话。在开始工作之前,请更新ISBUSY,然后将ReportViewer.RefreshReport()
执行到调度程序中,但使用低优先级dispatcherPriority,以便在UI更新后运行并表明它很忙。您的UI将在处理过程中被冻结,但至少您会给用户指示正在发生的事情。