忙碌的指示器不起作用



我正在Visual Studio 2015中构建一个MVVM Light WPF应用程序。它具有一个用户控件,其中包含一个 WindowsFormsHost,其中包含用于SQL Server报告服务服务本地报告的ReportViewerReportView.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.csIsBusy属性的定义:

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将在处理过程中被冻结,但至少您会给用户指示正在发生的事情。

最新更新