为长时间运行的方法实现WPF Progressbar

为长时间运行的方法实现WPF Progressbar,wpf,progress-bar,Wpf,Progress Bar,我们有一个三层架构(UI、BL、DAL)WPF应用程序。我需要处理大量行的WPF和DevExpress数据网格的加载。BL方法将返回要绑定到WPF数据网格的对象的可观察集合。如果记录的数量非常大,那么UI将变得不响应。因此,我们需要实现一个解决方案,在BL方法执行查询和处理数据时,显示一个进度条,其中显示完成工作的百分比。在这里,我需要在执行查询时立即获得记录总数,在处理每一行之后,我需要在标签中显示项目处理的当前索引,如“处理1/2000文档” 实现上述功能的最佳方法是什么。我们使用的是MVV

我们有一个三层架构(UI、BL、DAL)WPF应用程序。我需要处理大量行的WPF和DevExpress数据网格的加载。BL方法将返回要绑定到WPF数据网格的对象的可观察集合。如果记录的数量非常大,那么UI将变得不响应。因此,我们需要实现一个解决方案,在BL方法执行查询和处理数据时,显示一个进度条,其中显示完成工作的百分比。在这里,我需要在执行查询时立即获得记录总数,在处理每一行之后,我需要在标签中显示项目处理的当前索引,如“处理1/2000文档”

实现上述功能的最佳方法是什么。我们使用的是MVVM模式。我是否需要更改在BL中获取和处理记录的方式(当前是BL方法中的FETCH和处理(从datareader到自定义对象的映射值))。或者,我希望在用户滚动数据网格时以分页方式加载数据网格中的行

任何样品的链接是感激的

编辑: @爸爸,你的解决方案 1) 向视图模型添加新属性以获取TotalCount和PercentComplete。 2) 将viewmodel传递给搜索方法。 3) 使用BGW更新属性


以上似乎是一个可行的解决办法。但我很想知道是否有其他方法可以在不依赖viewmodel的情况下解决这个问题。是否有任何设计模式可用于此类操作?

因此您拥有所有行。您指的是什么处理?翻译渲染的显示状态将始终为100%,因为渲染完成后才会渲染

UI需要很长时间才能呈现2000行。有很多格式化和大小调整正在进行

使用“下一页”和“上一页”按钮将UI拆分为每页显示40行

如果DevExpress datagrid不支持虚拟化,请查找支持虚拟化的网格。对于速度,我喜欢ListView GridView

哇,支票。你在听。我给你更多


因此,如果这很快,那么立即获取整个ID列表(您可以获得总计数)。然后根据需要创建40个对象。如果你想变得更花哨,那就在后台创建下一个40。启动BackGroundWorker时禁用“下一步”按钮,并在“完成”对话框中启用它

您可以使用BackgroundWorker来处理此问题。它不会在获取数据时阻止用户界面,并会让用户界面保持响应。BackgroundWorker有一个ProgressChanged事件,可以很好地与ProgressBars配合使用

在我所从事的项目中,我在客户机服务/存储库中实现了BWs。您的视图模型可以对此类进行调用。这里的方法将实例化BWs、执行工作、报告进度并返回数据。您需要在UI上报告进度,因此在视图模型中设置一个属性,并将ProgressBar的值绑定到该属性,如下所示:

BackgroundWorker.RunWorkerCompleted += (o, e) =>
        {
            ...Update progress
        };
查看模型

private int _percentCompleted;
    [DefaultValue(0)]
    public int PercentCompleted
    {
        get { return _percentCompleted; }
        set
        {
            _percentCompleted = value;
            RaisePropertyChanged(() => this.PercentCompleted);
        }
    }
查看

<ProgressBar x:Name="SourceBatchUploadProgressBar"
                         Style="{StaticResource GreenProgressBar}" Grid.Column="1"  Grid.Row="1" 
                         Value="{Binding PercentCompleted, UpdateSourceTrigger=PropertyChanged}" 
                         Height="25" Width="200" Margin="5,0,10,5"/>

如果您想了解更多详细信息,请告诉我。

我认为这里的挑战在于,如果它是一个查询,就像在数据库查询中一样,除了“完成”之外,没有其他要报告的进度。如果OP正在处理查询结果,而这是一项耗时的任务,那么请给出完美的答案。@BUM正确答案。如果是消耗任务的数据库查询,那么BackgroundWorker的好处仅限于不阻塞UI。@我的问题是BL方法如何发送/更新它正在执行的任务的进度?它应该独立于视图模型。所以应该有某种机制在BL方法执行时从中获取进度。在我的例子中,过程如下:1)视图模型调用BL方法MyClass.Search(param1,Param2)。此方法的returnType是MyClass对象的ObservableCollection。2) 搜索方法首先执行查询并作为DataReader返回。然后我们从读取器中读取数据,并逐个映射到MyClass对象。因此,我需要在执行查询时通知UI关于总ROCODS的信息,并且在完成每行的datareader值到MyClass对象的映射时通知UI。那么,我们如何将BL的完成百分比发送到这里的视图模型呢?@saravana根据我对您场景的理解,我建议尝试以下方法。首先,将BackgroundWorker、TotalRecords(int)属性和PercentCompleted(int)属性添加到ViewModel中。第二,将视图模型传递给MyClass.Search()方法,并在此方法中报告TotalRecords,并更新BackgroundWorker.ProgressChanged和BackgroundWorker中的PercentComplete属性。RunWorkerCompleted事件处理程序。@Balm我在Big Daddy的回答中添加了更多的细节。在DevXPress和WPF datagrid中,虚拟化都已启用。对于查询,执行查询(使用LLBLGen ORM)需要几毫秒。将查询结果映射到业务对象需要更多的时间。因此,这与渲染无关。它是向用户提供有用的信息,直到BL方法返回可观察的集合。正如我在问题中所问的,如果无法从BL获取中间信息以查看模型,那么是否有任何方法可以在处理行时处理和查询结果并将其发送到查看模型?@saravana因此创建业务对象所需的时间比查询所需的时间长。不要试图告诉我渲染不是问题-我知道渲染2000行需要一段时间。你从我和大爸爸那里得到了正确的答案,你拒绝了。不要期望人们阅读完整问题陈述的评论-更新问题。@Balm,如果我的描述没有给你一个正确的图片,我很抱歉。请注意英语不是我的母语。我的意思是,在我的评论中,渲染不是一个直接的优先事项,g