WPF BindingList loading no ui issues mvvm
Install-Package Microsoft.Extensions.DependencyInjection;
Install-Package CommunityToolkit.mvvm;
private async Task InitData() { StatusMsg="Loading..."; BooksBindingList=new BindingList<Book>(); BooksBindingList.AllowEdit=true; BooksBindingList.AllowNew=true; BooksBindingList.AllowRemove=true; BooksBindingList.AddingNew+=BooksBindingList_AddingNew; await Task.Run(async () => { List<Book> booksList=new List<Book>(); for (int i = 0; i<10000000; i++) { Book bk = new Book() { Id=idService.GetID(), Name=nameService.GetName(), ISBN=iSBNService.GetISBN() }; booksList.Add(bk); if (i%1000000==0) { await PopulateBooksBindingList(booksList); } } if(booksList.Count>0) { await PopulateBooksBindingList(booksList); } await Application.Current.Dispatcher.InvokeAsync(() => { StatusMsg=$"Loaded {BooksBindingList.Count} items"; }); }); MessageBox.Show("Initialization finished!"); } private async Task PopulateBooksBindingList(List<Book> booksList) { await Application.Current.Dispatcher.InvokeAsync(() => { var tempList = booksList.ToList(); booksList.Clear(); foreach (Book bk in tempList) { BooksBindingList.Add(bk); } StatusMsg=$"Loaded {BooksBindingList.Count} items"; }); await Task.Delay(1); }
//app.cs using Microsoft.Extensions.DependencyInjection; using System.Configuration; using System.Data; using System.Windows; namespace WpfApp14 { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : Application { ServiceProvider serviceProvider; protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); var services = new ServiceCollection(); ConfigureServices(services); serviceProvider = services.BuildServiceProvider(); var mainWin = serviceProvider.GetRequiredService<MainWindow>(); mainWin?.Show(); } private void ConfigureServices(ServiceCollection services) { services.AddSingleton<IIDService, IDService>(); services.AddSingleton<INameService, NameService>(); services.AddSingleton<IISBNService, ISBNService>(); services.AddSingleton<MainWindow>(); services.AddSingleton<MainVM>(); } protected override void OnExit(ExitEventArgs e) { base.OnExit(e); } } } //mainwindow.xaml <Window x:Class="WpfApp14.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp14" WindowState="Maximized" mc:Ignorable="d" Title="{Binding StatusMsg,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Height="450" Width="800"> <Grid> <DataGrid ItemsSource="{Binding BooksBindingList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="{Binding DataContext.GridWidth,RelativeSource={RelativeSource AncestorType=Window}}" Height="{Binding DataContext.GridHeight,RelativeSource={RelativeSource AncestorType=Window}}" AutoGenerateColumns="False" CanUserAddRows="False" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling"> <DataGrid.Resources> <Style TargetType="DataGridRow"> <Setter Property="FontSize" Value="30"/> <Setter Property="HorizontalAlignment" Value="Center"/> <Setter Property="VerticalAlignment" Value="Center"/> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="FontSize" Value="40"/> <Setter Property="Foreground" Value="Red"/> </Trigger> </Style.Triggers> </Style> </DataGrid.Resources> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding Id}"/> <DataGridTextColumn Binding="{Binding Name}"/> <DataGridTextColumn Binding="{Binding ISBN}"/> </DataGrid.Columns> </DataGrid> </Grid> </Window> //mainwindow.cs using CommunityToolkit.Mvvm.ComponentModel; using System.ComponentModel; using System.Diagnostics.Eventing.Reader; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp14 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } public MainWindow(MainVM vm) { InitializeComponent(); this.DataContext=vm; this.SizeChanged+=MainWindow_SizeChanged; } private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e) { if (DataContext is MainVM vm) { var fe = this.Content as FrameworkElement; if (fe!=null) { vm.GridWidth=fe.ActualWidth; vm.GridHeight=fe.ActualHeight; } } } } public partial class MainVM : ObservableObject { IIDService idService; IISBNService iSBNService; INameService nameService; public MainVM(IIDService idServiceValue, IISBNService iSBNServiceValue, INameService nameServiceValue) { idService=idServiceValue; iSBNService=iSBNServiceValue; nameService=nameServiceValue; InitData(); } private async Task InitData() { StatusMsg="Loading..."; BooksBindingList=new BindingList<Book>(); BooksBindingList.AllowEdit=true; BooksBindingList.AllowNew=true; BooksBindingList.AllowRemove=true; BooksBindingList.AddingNew+=BooksBindingList_AddingNew; await Task.Run(async () => { List<Book> booksList=new List<Book>(); for (int i = 0; i<10000000; i++) { Book bk = new Book() { Id=idService.GetID(), Name=nameService.GetName(), ISBN=iSBNService.GetISBN() }; booksList.Add(bk); if (i%1000000==0) { await PopulateBooksBindingList(booksList); } } if(booksList.Count>0) { await PopulateBooksBindingList(booksList); } await Application.Current.Dispatcher.InvokeAsync(() => { StatusMsg=$"Loaded {BooksBindingList.Count} items"; }); }); MessageBox.Show("Initialization finished!"); } private async Task PopulateBooksBindingList(List<Book> booksList) { await Application.Current.Dispatcher.InvokeAsync(() => { var tempList = booksList.ToList(); booksList.Clear(); foreach (Book bk in tempList) { BooksBindingList.Add(bk); } StatusMsg=$"Loaded {BooksBindingList.Count} items"; }); await Task.Delay(1); } private void BooksBindingList_AddingNew(object? sender, AddingNewEventArgs e) { BooksBindingList.Add(new Book() { Id = idService.GetID(), Name=nameService.GetName(), ISBN = iSBNService.GetISBN() }); } [ObservableProperty] private double gridWidth; [ObservableProperty] private double gridHeight; [ObservableProperty] private BindingList<Book> booksBindingList; [ObservableProperty] private string statusMsg; } public class Book { public int Id { get; set; } public string Name { get; set; } public string ISBN { get; set; } } public interface IIDService { int GetID(); } public class IDService : IIDService { int id = 0; public int GetID() { return ++id; } } public interface INameService { string GetName(); } public class NameService : INameService { int idx = 0; public string GetName() { return $"Name_{++idx}"; } } public interface IISBNService { string GetISBN(); } public class ISBNService : IISBNService { int idx = 0; public string GetISBN() { return $"ISBN_{++idx}_{Guid.NewGuid():N}"; } } }