





















<ItemsControl ItemsSource="{Binding BooksCollection}"> <ItemsControl.Template> <ControlTemplate TargetType="ItemsControl"> <DockPanel LastChildFill="True"> <TextBlock Text="IsItemsHost=True" FontSize="50" DockPanel.Dock="Top"/> <ScrollViewer CanContentScroll="True"> <VirtualizingStackPanel IsItemsHost="True" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ScrollViewer.CanContentScroll="True" ScrollViewer.IsDeferredScrollingEnabled="True" VirtualizingPanel.CacheLength="2,2" VirtualizingPanel.CacheLengthUnit="Item"> </VirtualizingStackPanel> </ScrollViewer> </DockPanel> </ControlTemplate> </ItemsControl.Template> <ItemsControl.ItemTemplate> <DataTemplate> <Grid Margin="5" Width="{x:Static SystemParameters.FullPrimaryScreenWidth}" Height="{x:Static SystemParameters.FullPrimaryScreenHeight}"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.Resources> <Style TargetType="TextBlock"> <Setter Property="FontSize" Value="30"/> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="FontSize" Value="50"/> <Setter Property="Foreground" Value="Red"/> </Trigger> </Style.Triggers> </Style> </Grid.Resources> <Image Source="{Binding ImgUrl,Converter={StaticResource ImgConverter}}" Stretch="Uniform" Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" Grid.ColumnSpan="2"/> <TextBlock Text="{Binding Id}" Grid.Row="0" Grid.Column="0"/> <TextBlock Text="{Binding Name}" Grid.Row="0" Grid.Column="1"/> <TextBlock Text="{Binding ISBN}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"/> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>

<Window x:Class="WpfApp12.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:WpfApp12" mc:Ignorable="d" WindowState="Maximized" Title="{Binding MainTitle}"> <Window.DataContext> <local:MainVM/> </Window.DataContext> <Window.Resources> <local:ImgConverter x:Key="ImgConverter"/> </Window.Resources> <Grid> <ItemsControl ItemsSource="{Binding BooksCollection}"> <ItemsControl.Template> <ControlTemplate TargetType="ItemsControl"> <DockPanel LastChildFill="True"> <TextBlock Text="IsItemsHost=True" FontSize="50" DockPanel.Dock="Top"/> <ScrollViewer CanContentScroll="True"> <VirtualizingStackPanel IsItemsHost="True" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ScrollViewer.CanContentScroll="True" ScrollViewer.IsDeferredScrollingEnabled="True" VirtualizingPanel.CacheLength="2,2" VirtualizingPanel.CacheLengthUnit="Item"> </VirtualizingStackPanel> </ScrollViewer> </DockPanel> </ControlTemplate> </ItemsControl.Template> <ItemsControl.ItemTemplate> <DataTemplate> <Grid Margin="5" Width="{x:Static SystemParameters.FullPrimaryScreenWidth}" Height="{x:Static SystemParameters.FullPrimaryScreenHeight}"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.Resources> <Style TargetType="TextBlock"> <Setter Property="FontSize" Value="30"/> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="FontSize" Value="50"/> <Setter Property="Foreground" Value="Red"/> </Trigger> </Style.Triggers> </Style> </Grid.Resources> <Image Source="{Binding ImgUrl,Converter={StaticResource ImgConverter}}" Stretch="Uniform" Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" Grid.ColumnSpan="2"/> <TextBlock Text="{Binding Id}" Grid.Row="0" Grid.Column="0"/> <TextBlock Text="{Binding Name}" Grid.Row="0" Grid.Column="1"/> <TextBlock Text="{Binding ISBN}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"/> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Grid> </Window> using System.Collections.ObjectModel; using System.ComponentModel; using System.Globalization; using System.IO; using System.Runtime.CompilerServices; 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.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp12 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } public class MainVM : INotifyPropertyChanged { private DateTime startTime; public MainVM() { Task.Run(async () => { await InitBooksCollection(52600000); }); } public async Task InitBooksCollection(int cnt = 100000) { BooksCollection = new ObservableCollection<Book>(); List<Book> booksList = new List<Book>(); var imgDir = @"../../../Images"; if (!Directory.Exists(imgDir)) { return; } var imgs = Directory.GetFiles(imgDir); if (imgs == null || !imgs.Any()) { return; } int imgsCount = imgs.Count(); startTime = DateTime.Now; for (int i = 1; i < cnt + 1; i++) { booksList.Add(new Book() { Id = i, Name = $"Name_{i}", ISBN = $"ISBN_{i}_{Guid.NewGuid():N}", ImgUrl = $"{imgs[i % imgsCount]}" }); if (i < 1000 && i % 200 == 0) { await PopulateBooksCollectionAsync(booksList); await Task.Delay(1); } else if (i % 1000000 == 0) { await PopulateBooksCollectionAsync(booksList); await Task.Delay(1); } } if (booksList.Any()) { await PopulateBooksCollectionAsync(booksList); } } private async Task PopulateBooksCollectionAsync(List<Book> booksList) { var tempList = booksList.ToList(); await Application.Current.Dispatcher.InvokeAsync(() => { foreach (var bk in tempList) { BooksCollection.Add(bk); } MainTitle = $"{DateTime.Now},loaded {BooksCollection.Count} items,{GetMem()},{GetTimeCost()}"; booksList.Clear(); }, System.Windows.Threading.DispatcherPriority.Background); } public string GetTimeCost() { var dtSpan = DateTime.Now.Subtract(startTime); return $"Time cost {dtSpan.TotalSeconds:0.00} seconds"; } private string GetMem() { return $"{System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 / 1024 / 1024:N2} M"; } private string mainTitle = ""; public string MainTitle { get { return mainTitle; } set { if (value != mainTitle) { mainTitle = value; OnPropertyChanged(); } } } private ObservableCollection<Book> booksCollection; public ObservableCollection<Book> BooksCollection { get { return booksCollection; } set { if (value != booksCollection) { booksCollection = value; OnPropertyChanged(); } } } public event PropertyChangedEventHandler? PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propertyName = "") { var handler = PropertyChanged; handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class ImgConverter : IValueConverter { private Dictionary<string, ImageSource> imgCache = new Dictionary<string, ImageSource>(); private readonly object objLock = new object(); public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var imgUrl = value?.ToString(); if (string.IsNullOrWhiteSpace(imgUrl) || !File.Exists(imgUrl)) { return null; } lock (objLock) { if (imgCache.ContainsKey(imgUrl)) { return imgCache[imgUrl]; } BitmapImage bmi = new BitmapImage(); bmi.BeginInit(); bmi.UriSource = new Uri(imgUrl, UriKind.RelativeOrAbsolute); //bmi.DecodePixelWidth = 1200; //bmi.DecodePixelHeight = 700; bmi.CacheOption = BitmapCacheOption.OnLoad; bmi.EndInit(); if (bmi.CanFreeze) { bmi.Freeze(); } imgCache[imgUrl] = bmi; return bmi; } return null; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return DependencyProperty.UnsetValue; } } public class DelCommand : ICommand { private Action<object?>? execute; private Predicate<object?>? canExecute; public DelCommand(Action<object?>? executeValue, Predicate<object?>? canExecuteValue = null) { execute = executeValue; canExecute = canExecuteValue; } public event EventHandler? CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object? parameter) { return canExecute == null ? true : canExecute(parameter); } public void Execute(object? parameter) { execute?.Invoke(parameter); } } public class Book { public int Id { get; set; } public string Name { get; set; } public string ISBN { get; set; } public string ImgUrl { get; set; } } }

<ItemsControl ItemsSource="{Binding BooksCollection}"> <ItemsControl.Template> <ControlTemplate TargetType="ItemsControl"> <ScrollViewer CanContentScroll="True"> <VirtualizingStackPanel IsItemsHost="True" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ScrollViewer.CanContentScroll="True" ScrollViewer.IsDeferredScrollingEnabled="True" VirtualizingPanel.CacheLength="2,2" VirtualizingPanel.CacheLengthUnit="Item"/> </ScrollViewer> </ControlTemplate> </ItemsControl.Template> <ItemsControl.ItemTemplate> <DataTemplate> <Grid Margin="5" Width="{x:Static SystemParameters.FullPrimaryScreenWidth}" Height="{x:Static SystemParameters.FullPrimaryScreenHeight}"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.Resources> <Style TargetType="TextBlock"> <Setter Property="FontSize" Value="30"/> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="FontSize" Value="50"/> <Setter Property="Foreground" Value="Red"/> </Trigger> </Style.Triggers> </Style> </Grid.Resources> <Image Source="{Binding ImgUrl,Converter={StaticResource ImgConverter}}" Stretch="Uniform" Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" Grid.ColumnSpan="2"/> <TextBlock Text="{Binding Id}" Grid.Row="0" Grid.Column="0"/> <TextBlock Text="{Binding Name}" Grid.Row="0" Grid.Column="1"/> <TextBlock Text="{Binding ISBN}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"/> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
<Window x:Class="WpfApp12.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:WpfApp12" mc:Ignorable="d" WindowState="Maximized" Title="{Binding MainTitle}"> <Window.DataContext> <local:MainVM/> </Window.DataContext> <Window.Resources> <local:ImgConverter x:Key="ImgConverter"/> </Window.Resources> <Grid> <ItemsControl ItemsSource="{Binding BooksCollection}"> <ItemsControl.Template> <ControlTemplate TargetType="ItemsControl"> <ScrollViewer CanContentScroll="True"> <VirtualizingStackPanel IsItemsHost="True" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ScrollViewer.CanContentScroll="True" ScrollViewer.IsDeferredScrollingEnabled="True" VirtualizingPanel.CacheLength="2,2" VirtualizingPanel.CacheLengthUnit="Item"/> </ScrollViewer> </ControlTemplate> </ItemsControl.Template> <ItemsControl.ItemTemplate> <DataTemplate> <Grid Margin="5" Width="{x:Static SystemParameters.FullPrimaryScreenWidth}" Height="{x:Static SystemParameters.FullPrimaryScreenHeight}"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.Resources> <Style TargetType="TextBlock"> <Setter Property="FontSize" Value="30"/> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="FontSize" Value="50"/> <Setter Property="Foreground" Value="Red"/> </Trigger> </Style.Triggers> </Style> </Grid.Resources> <Image Source="{Binding ImgUrl,Converter={StaticResource ImgConverter}}" Stretch="Uniform" Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" Grid.ColumnSpan="2"/> <TextBlock Text="{Binding Id}" Grid.Row="0" Grid.Column="0"/> <TextBlock Text="{Binding Name}" Grid.Row="0" Grid.Column="1"/> <TextBlock Text="{Binding ISBN}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"/> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Grid> </Window> using System.Collections.ObjectModel; using System.ComponentModel; using System.Globalization; using System.IO; using System.Runtime.CompilerServices; 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.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp12 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } public class MainVM : INotifyPropertyChanged { private DateTime startTime; public MainVM() { Task.Run(async () => { await InitBooksCollection(52600000); }); } public async Task InitBooksCollection(int cnt = 100000) { BooksCollection = new ObservableCollection<Book>(); List<Book> booksList = new List<Book>(); var imgDir = @"../../../Images"; if (!Directory.Exists(imgDir)) { return; } var imgs = Directory.GetFiles(imgDir); if (imgs == null || !imgs.Any()) { return; } int imgsCount = imgs.Count(); startTime = DateTime.Now; for (int i = 1; i < cnt + 1; i++) { booksList.Add(new Book() { Id = i, Name = $"Name_{i}", ISBN = $"ISBN_{i}_{Guid.NewGuid():N}", ImgUrl = $"{imgs[i % imgsCount]}" }); if (i < 1000 && i % 200 == 0) { await PopulateBooksCollectionAsync(booksList); await Task.Delay(1); } else if (i % 1000000 == 0) { await PopulateBooksCollectionAsync(booksList); await Task.Delay(1); } } if (booksList.Any()) { await PopulateBooksCollectionAsync(booksList); } } private async Task PopulateBooksCollectionAsync(List<Book> booksList) { var tempList = booksList.ToList(); await Application.Current.Dispatcher.InvokeAsync(() => { foreach (var bk in tempList) { BooksCollection.Add(bk); } MainTitle = $"{DateTime.Now},loaded {BooksCollection.Count} items,{GetMem()},{GetTimeCost()}"; booksList.Clear(); }, System.Windows.Threading.DispatcherPriority.Background); } public string GetTimeCost() { var dtSpan = DateTime.Now.Subtract(startTime); return $"Time cost {dtSpan.TotalSeconds:0.00} seconds"; } private string GetMem() { return $"{System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 / 1024 / 1024:N2} M"; } private string mainTitle = ""; public string MainTitle { get { return mainTitle; } set { if (value != mainTitle) { mainTitle = value; OnPropertyChanged(); } } } private ObservableCollection<Book> booksCollection; public ObservableCollection<Book> BooksCollection { get { return booksCollection; } set { if (value != booksCollection) { booksCollection = value; OnPropertyChanged(); } } } public event PropertyChangedEventHandler? PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propertyName = "") { var handler = PropertyChanged; handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class ImgConverter : IValueConverter { private Dictionary<string, ImageSource> imgCache = new Dictionary<string, ImageSource>(); private readonly object objLock = new object(); public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var imgUrl = value?.ToString(); if (string.IsNullOrWhiteSpace(imgUrl) || !File.Exists(imgUrl)) { return null; } lock (objLock) { if (imgCache.ContainsKey(imgUrl)) { return imgCache[imgUrl]; } BitmapImage bmi = new BitmapImage(); bmi.BeginInit(); bmi.UriSource = new Uri(imgUrl, UriKind.RelativeOrAbsolute); //bmi.DecodePixelWidth = 1200; //bmi.DecodePixelHeight = 700; bmi.CacheOption = BitmapCacheOption.OnLoad; bmi.EndInit(); if (bmi.CanFreeze) { bmi.Freeze(); } imgCache[imgUrl] = bmi; return bmi; } return null; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return DependencyProperty.UnsetValue; } } public class DelCommand : ICommand { private Action<object?>? execute; private Predicate<object?>? canExecute; public DelCommand(Action<object?>? executeValue, Predicate<object?>? canExecuteValue = null) { execute = executeValue; canExecute = canExecuteValue; } public event EventHandler? CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object? parameter) { return canExecute == null ? true : canExecute(parameter); } public void Execute(object? parameter) { execute?.Invoke(parameter); } } public class Book { public int Id { get; set; } public string Name { get; set; } public string ISBN { get; set; } public string ImgUrl { get; set; } } }



此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。