使用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
相关产品推荐
相关产品推荐

