当前位置: 首页 > news >正文

WPF ListBox loaded 76.6M items with imagesource

 

Install-Package Microsoft.Extensions.DependencyInjection;
Install-Package CommunityToolkit.mvvm;

 

 

public async Task InitDataAsync()
{watch.Start();string imgDir = @"../../../Images";if (!Directory.Exists(imgDir)){return;}var imgs = Directory.GetFiles(imgDir);if (imgs==null ||!imgs.Any()){return;}int imgsCount = imgs.Count();BooksCollection=new ObservableCollection<Book>();List<Book> booksList = new List<Book>();for (int i = 1; i<100000001; i++){booksList.Add(new Book(){Id=idService.GetID(),Name=nameService.GetName(),ISBN=isbnService.GetISBN(),Author=$"Author_{i}",Title=$"Title_{i}",Topic=$"Topic_{i}",//ImgSource=GetImgSourceViaUrl(imgs[i%imgsCount]),ImgUrl=imgs[i%imgsCount]});if (i<1001 && i%100==0){await PopulateBooksCollectionAsync(booksList);}else if (i>1000 && i%100000==0){await PopulateBooksCollectionAsync(booksList);}}if (booksList.Any()){await PopulateBooksCollectionAsync(booksList);}
}private ImageSource GetImgSourceViaUrl(string imgUrl)
{if (imgDicCache.TryGetValue(imgUrl, out var img)){return img;}BitmapImage bmi = new BitmapImage();bmi.BeginInit();bmi.CacheOption= BitmapCacheOption.OnDemand;bmi.UriSource=new Uri(imgUrl, UriKind.RelativeOrAbsolute);bmi.EndInit();bmi.Freeze();imgDicCache[imgUrl] = bmi;return bmi;
}private async Task PopulateBooksCollectionAsync(List<Book> booksList)
{var tempList = booksList.ToList();booksList.Clear();await Application.Current.Dispatcher.InvokeAsync(() =>{foreach (var bk in tempList){BooksCollection.Add(bk);}StatusMsg=$"Loaded {BooksCollection.Count} items,{GetMemory()},{GetTimeCost()}";}, System.Windows.Threading.DispatcherPriority.Background);// Yield to keep UI responsive//await Task.Delay(1);
}private string GetMemory()
{var memory = Process.GetCurrentProcess().PrivateMemorySize64/1024.0d/1024.0d;return $"Memory:{memory.ToString("#,##0")} M";
}private string GetTimeCost()
{return $"Time cost:{watch.Elapsed.TotalSeconds} seconds!";  
}

 

 

 

 

 

 

image

 

 

 

//app.xaml
<Application x:Class="WpfApp30.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:WpfApp30"><Application.Resources></Application.Resources>
</Application>//App.xaml.cs
using Microsoft.Extensions.DependencyInjection;
using System.Configuration;
using System.Data;
using System.Windows;namespace WpfApp30
{/// <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);serviceProvider?.Dispose();}}}//MainWindow.xaml
<Window x:Class="WpfApp30.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:WpfApp30"WindowState="Maximized"mc:Ignorable="d"Title="{Binding StatusMsg,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"Height="450" Width="800"><Window.Resources><local:ImgPathConverter x:Key="ImgPathConverter"/></Window.Resources><Grid><ListBox ItemsSource="{Binding BooksCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"VirtualizingPanel.IsVirtualizing="True"VirtualizingPanel.VirtualizationMode="Recycling"VirtualizingPanel.CacheLengthUnit="Pixel"ScrollViewer.CanContentScroll="True"ScrollViewer.IsDeferredScrollingEnabled="True"Background="Transparent"><ListBox.ItemTemplate><DataTemplate><Grid Width="{Binding DataContext.GridWidth,RelativeSource={RelativeSource AncestorType=Window}}"Height="{Binding DataContext.GridHeight,RelativeSource={RelativeSource AncestorType=Window}}"><Grid.Background><ImageBrush ImageSource="{Binding ImgUrl,Converter={StaticResource ImgPathConverter}}"/></Grid.Background><Grid.Resources><Style TargetType="TextBlock"><Setter Property="FontSize" Value="30"/><Setter Property="Effect"><Setter.Value><DropShadowEffect ShadowDepth="1" Color="Black"Opacity="0.8"/></Setter.Value></Setter><Style.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter Property="FontSize" Value="50"/><Setter Property="Foreground" Value="Red"/></Trigger></Style.Triggers></Style></Grid.Resources><Grid.RowDefinitions><RowDefinition/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><TextBlock Text="{Binding Id}" Grid.Row="0" Grid.Column="0"/><TextBlock Text="{Binding Name}" Grid.Row="0" Grid.Column="1"/><TextBlock Text="{Binding Title}" Grid.Row="0" Grid.Column="2"/><TextBlock Text="{Binding Topic}" Grid.Row="0" Grid.Column="3"/><TextBlock Text="{Binding Author}" Grid.Row="0" Grid.Column="4"/><TextBlock Text="{Binding ISBN}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="5"/></Grid></DataTemplate></ListBox.ItemTemplate></ListBox></Grid>
</Window>//MainWindow.xaml.cs
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.Intrinsics.X86;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;namespace WpfApp30
{/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}public MainWindow(MainVM vm){InitializeComponent();RenderOptions.ProcessRenderMode=RenderMode.Default;this.DataContext=vm;this.Loaded+=async (s, e) =>{await LoadDataAsync(s, e);};this.SizeChanged+=MainWindow_SizeChanged;}private async Task LoadDataAsync(object s, RoutedEventArgs e){if (DataContext is MainVM vm){await vm.InitDataAsync();}}private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e){if (this.DataContext is MainVM vm){var fe = this.Content as FrameworkElement;if (fe!=null){vm.GridWidth=fe.ActualWidth;vm.GridHeight=fe.ActualHeight/2;}}}}public partial class MainVM : ObservableObject{IIDService idService;INameService nameService;IISBNService isbnService;private Dictionary<string, ImageSource> imgDicCache = new Dictionary<string, ImageSource>();private Stopwatch watch = new Stopwatch();public MainVM(IIDService idServiceValue, INameService nameServiceValue, IISBNService isbnServiceValue){idService = idServiceValue;nameService = nameServiceValue;isbnService = isbnServiceValue;}public async Task InitDataAsync(){watch.Start();string imgDir = @"../../../Images";if (!Directory.Exists(imgDir)){return;}var imgs = Directory.GetFiles(imgDir);if (imgs==null ||!imgs.Any()){return;}int imgsCount = imgs.Count();BooksCollection=new ObservableCollection<Book>();List<Book> booksList = new List<Book>();for (int i = 1; i<100000001; i++){booksList.Add(new Book(){Id=idService.GetID(),Name=nameService.GetName(),ISBN=isbnService.GetISBN(),Author=$"Author_{i}",Title=$"Title_{i}",Topic=$"Topic_{i}",//ImgSource=GetImgSourceViaUrl(imgs[i%imgsCount]),ImgUrl=imgs[i%imgsCount]});if (i<1001 && i%100==0){await PopulateBooksCollectionAsync(booksList);}else if (i>1000 && i%100000==0){await PopulateBooksCollectionAsync(booksList);}}if (booksList.Any()){await PopulateBooksCollectionAsync(booksList);}}private ImageSource GetImgSourceViaUrl(string imgUrl){if (imgDicCache.TryGetValue(imgUrl, out var img)){return img;}BitmapImage bmi = new BitmapImage();bmi.BeginInit();bmi.CacheOption= BitmapCacheOption.OnDemand;bmi.UriSource=new Uri(imgUrl, UriKind.RelativeOrAbsolute);bmi.EndInit();bmi.Freeze();imgDicCache[imgUrl] = bmi;return bmi;}private async Task PopulateBooksCollectionAsync(List<Book> booksList){var tempList = booksList.ToList();booksList.Clear();await Application.Current.Dispatcher.InvokeAsync(() =>{foreach (var bk in tempList){BooksCollection.Add(bk);}StatusMsg=$"Loaded {BooksCollection.Count} items,{GetMemory()},{GetTimeCost()}";}, System.Windows.Threading.DispatcherPriority.Background);// Yield to keep UI responsive//await Task.Delay(1);
        }private string GetMemory(){var memory = Process.GetCurrentProcess().PrivateMemorySize64/1024.0d/1024.0d;return $"Memory:{memory.ToString("#,##0")} M";}private string GetTimeCost(){return $"Time cost:{watch.Elapsed.TotalSeconds} seconds!";  }[ObservableProperty]private double gridWidth;[ObservableProperty]private double gridHeight;[ObservableProperty]private ObservableCollection<Book> booksCollection;[ObservableProperty]private string statusMsg;}public class Book{public int Id { get; set; }public string Name { get; set; }public string Title { get; set; }public string Topic { get; set; }public string Author { get; set; }public string ISBN { get; set; }public string ImgUrl { get; set; }  //public ImageSource ImgSource { get; set; }
    }public interface IIDService{int GetID();}public class IDService : IIDService{int id = 0;public int GetID(){return Interlocked.Increment(ref id);}}public interface INameService{string GetName();}public class NameService : INameService{int idx = 0;public string GetName(){return $"Name_{Interlocked.Increment(ref idx)}";}}public interface IISBNService{string GetISBN();}public class ISBNService : IISBNService{int idx = 0;public string GetISBN(){return $"ISBN_{Interlocked.Increment(ref idx)}_{Guid.NewGuid():N}";}}public class ImgPathConverter : IValueConverter{ConcurrentDictionary<string, ImageSource> dicCache = new ConcurrentDictionary<string, ImageSource>();public object Convert(object value, Type targetType, object parameter, CultureInfo culture){try{if (value is string imgUrl && File.Exists(imgUrl)){if (dicCache.TryGetValue(imgUrl, out ImageSource img)){return img;}BitmapImage bmi = new BitmapImage();bmi.BeginInit();bmi.CacheOption= BitmapCacheOption.OnDemand;bmi.UriSource=new Uri(imgUrl, UriKind.RelativeOrAbsolute);bmi.EndInit();bmi.Freeze();dicCache[imgUrl]=bmi;return bmi;}}catch (Exception ex){return null;}return null;}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){throw new NotImplementedException();}}
}

 

http://www.gsyq.cn/news/9494.html

相关文章:

  • 【数据结构】双向链表 - 指南
  • 告别“能源糊涂账”:MyEMS如何帮企业把能耗数据“算明白、用到位”
  • 完整教程:ElasticSearch倒排索引原理
  • 负载排查和分析三
  • 完整教程:线程、进程、协程
  • CF913G Power Substring
  • ES集群部署-EFK架构实战 - 实践
  • 《BOE解忧实验室》第四季圆满收官 以科技重塑文化生活新范式
  • 洛谷P2261 [CQOI2007] 余数求和
  • 完整教程:uniapp、devceo华为鸿蒙运行模拟器报错:未开启Hyper-V
  • 深入解析:08_多层感知机
  • (一)React面试(虚拟DOM/类组件) - 详解
  • 浏览器访问页面卡顿刷新页面方法
  • 完整教程:散斑深度相机原理
  • k8s Understanding Kubernetes Security Components
  • G1垃圾回收过程
  • Trellix自动化大规模修复开源漏洞,已修补超6万个项目
  • 人形机器人 —— 电机控制的三种模式 —— 力矩、速度、位置
  • 解决Windows更新后WPF代码报TypeLoadException异常的困难
  • PC与基恩士PLC通信的C#实现
  • Excel 表格技能
  • rk3588的ai功能和deepseek
  • EPSON L1300打印机清零教程
  • tomcat CPU数量和线程数的关系
  • python处理Excel单机小程序:匹数据,增强版VLookup
  • CF623B Array GCD
  • Python爬虫实现双色球历史数据抓取
  • 酵母细胞工厂全球调控策略研究进展:从遗传编辑到智能响应
  • Java实现双色球历史开奖对比器
  • 成都恒利泰HT-SCA-4-10+是一款1分4射频功分器