You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Background Worker仍出现WPF应用UI冻结问题求助

WPF DataGrid加载与筛选UI冻结问题解决记录

我开发了一款WPF应用,从数据库获取数据并在主窗口的DataGrid中展示,最多显示约5000条数据。我可以接受数据展示的延迟,但希望在此期间显示加载动画。然而,即便使用Background Worker更新CollectionViewSource,UI仍会在显示数据行前出现冻结。请问是否可以在不冻结UI的情况下添加所有数据行?另外,对CollectionViewSource应用筛选时也会导致UI冻结,若有可能也希望解决该问题。

【2023年1月6日更新】:根据BionicCode和Andy的建议修改后,目前运行流畅,感谢帮助!


相关代码

DataGrid的XAML代码

<DataGrid Grid.Column="1" Name="documentDisplay" ItemsSource="{Binding Source={StaticResource cvsDocuments}, UpdateSourceTrigger=PropertyChanged, IsAsync=True}" AutoGenerateColumns="False" 
          Style="{StaticResource DataGridDefault}" ScrollViewer.CanContentScroll="True"
          HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" ColumnWidth="*">

CollectionViewSource的XAML代码

<Window.Resources>
        <local:Documents x:Key="documents" />
        <CollectionViewSource x:Key="cvsDocuments" Source="{StaticResource documents}"
                                Filter="DocumentFilter">

数据库取数后调用的函数代码

Documents _documents = (Documents)this.Resources["documents"];
            
BindingOperations.EnableCollectionSynchronization(_documents, _itemsLock);

if (!populateDocumentWorker.IsBusy)
{
    progressBar.Visibility = Visibility.Visible;
    populateDocumentWorker.RunWorkerAsync(jobId);
}

Worker内部代码

Documents _documents = (Documents)this.Resources["documents"];

lock (_itemsLock)
{
    _documents.Clear();
    _documents.AddRange(documentResult.documents);
}

ObservableCollection类代码

public class Documents : ObservableCollection<Document>, INotifyPropertyChanged
{
    private bool _surpressNotification = false;

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (!_surpressNotification)
        {
            base.OnCollectionChanged(e);
        }
    }

    public void AddRange(IEnumerable<Document> list)
    {
        if(list == null)
        {
            throw new ArgumentNullException("list");

            _surpressNotification = true;
        }
        
        foreach(Document[] batch in list.Chunk(25))
        {
            foreach (Document item in batch)
            {
                Add(item);
            }
            _surpressNotification = false;
        }
 
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }
}

Document实体类代码

public class Document : INotifyPropertyChanged, IEditableObject
{
    public int Id { get; set; }
    public string Number { get; set; }
    public string Title { get; set; }
    public string Revision { get; set; }
    public string Discipline { get; set; }
    public string Type { get; set;  }
    public string Status { get; set; }
    public DateTime Date { get; set; }
    public string IssueDescription { get; set; }
    public string Path { get; set; }
    public string Extension { get; set; }

    // Implement INotifyPropertyChanged interface.
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(String info)
    {
        if(PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    private void NotifyPropertyChanged(string propertyName)
    {

    }

    // Implement IEditableObject interface.
    public void BeginEdit()
    {

    }

    public void CancelEdit()
    {

    }

    public void EndEdit()
    {

    }
}

筛选函数代码

private void DocumentFilter(object sender, FilterEventArgs e)
{
    //Create list of all selected disciplines
    List<string> selectedDisciplines = new List<string>();
    
    foreach(var item in disciplineFilters.SelectedItems)
    {
        selectedDisciplines.Add(item.ToString());
    }

    //Create list of all select document types
    List<string> selectedDocumentTypes = new List<string>();

    foreach(var item in docTypeFilters.SelectedItems)
    {
        selectedDocumentTypes.Add(item.ToString());
    }

    // Create list of all selected file tpyes
    List<string> selectedFileTypes = new List<string>();

    foreach(var item in fileTypeFilters.SelectedItems)
    {
        selectedFileTypes.Add(item.ToString());
    }

    //Cast event item as document object
    Document doc = e.Item as Document;

    //Apply filter to select discplines and document types
    if( doc != null)
    {
        if (selectedDisciplines.Contains(doc.Discipline) && selectedDocumentTypes.Contains(doc.Type) && selectedFileTypes.Contains(doc.Extension))
        {
            e.Accepted = true;
        } else
        {
            e.Accepted = false;
        }
    }
}

内容的提问来源于stack exchange,提问作者dancolewye

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:35:23