WPF WrapPanel虚拟化
驚鏵 人气:0WrapPanel 实现虚拟化
1.框架使用大于等于.NET40
;
2.Visual Studio 2022;
3.项目使用 MIT 开源许可协议;
4.众所周知 WPF 的 StackPanel 在加载大量数据时性能会特别差,但是官方提供了一个虚拟化容器VirtualizingStackPanel;
VirtualizingStackPanel.IsVirtualizing
附加属性设置为true
时就开启虚拟化。VirtualizingStackPanel.IsVirtualizing
附加属性设置为false
其VirtualizingStackPanel
行为与普通StackPanel
属性的行为相同。
5.WrapPanel 默认是不支持虚拟化的,所以需要自行实现。
1) VirtualizingWrapPanel 查看源码 | VirtualizingWrapPanel 查看源码。
2) 准备数据HospitalList.cs如下:
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Windows.Media; namespace WPFDevelopers.Minimal.Sample.Models { public class HospitalList : ObservableCollection<Hospital> { public HospitalList() { var hospitals = new string[] { "No. 189, Grove St, Los Angeles", "No. 3669, Grove St, Los Angeles" }; var names = new string[] { "Doctor Fang", "Judge Qu" }; var images = new string[] { "http://pic2.zhimg.com/80/v2-0711e97955adc9be9fbcff67e1007535_720w.jpg", //"http://pic2.zhimg.com/80/v2-5b7f84c63075ba9771f6e6dc29a54615_720w.jpg", "http://pic3.zhimg.com/80/v2-a3d6d8832090520e7ed6c748a8698e4e_720w.jpg", "http://pic3.zhimg.com/80/v2-de7554ac9667a59255fe002bb8753ab6_720w.jpg" }; var state = 0; for (var i = 1; i < 10000; i++) { Add(new Hospital { Id = $"9999{i}", DoctorName = i % 2 == 0 ? names[0]:names[1], HospitalName = i % 2 == 0 ? hospitals[0] : hospitals[1] ,State = state ,UserImage = images[state] }); state++; if (state > 2) state = 0; } } } public class Hospital { public string Id { get; set; } public string DoctorName { get; set; } public string HospitalName { get; set; } public string UserImage { get; set; } public int State { get; set; } } }
3) 新建展示VirtualizingWrapPanelExample.xaml如下:
<ws:Window x:Class="WPFDevelopers.Minimal.Sample.ExampleViews.VirtualizingWrapPanelExample" 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:ws="https://github.com/WPFDevelopersOrg/WPFDevelopers.Minimal" xmlns:local="clr-namespace:WPFDevelopers.Minimal.Sample.ExampleViews" xmlns:model="clr-namespace:WPFDevelopers.Minimal.Sample.Models" xmlns:converts="clr-namespace:WPFDevelopers.Minimal.Sample.Converts" mc:Ignorable="d" WindowStartupLocation="CenterScreen" Title="System V1.0" Height="450" Width="900"> <Window.Resources> <model:HospitalList x:Key="myHospitalList"/> <converts:StateConvert x:Key="stateConvert"></converts:StateConvert> </Window.Resources> <Grid Margin="4"> <WrapPanel HorizontalAlignment="Left"> <WrapPanel.Resources> <Style TargetType="Border"> <Setter Property="Padding" Value="2"></Setter> <Setter Property="BorderThickness" Value="1"></Setter> </Style> <Style TargetType="Rectangle"> <Setter Property="Width" Value="15"></Setter> <Setter Property="Height" Value="15"></Setter> <Setter Property="Opacity" Value=".2"></Setter> </Style> </WrapPanel.Resources> <WrapPanel> <Border BorderBrush="Green"> <Rectangle Fill="Green"/> </Border> <TextBlock Text="Idle" Foreground="Black" Margin="4,0"/> </WrapPanel> <WrapPanel> <Border BorderBrush="Orange"> <Rectangle Fill="Orange"/> </Border> <TextBlock Text="Slightly Idle" Foreground="Black" Margin="4,0"/> </WrapPanel> <WrapPanel> <Border BorderBrush="Red"> <Rectangle Fill="Red"/> </Border> <TextBlock Text="Busy" Foreground="Black" Margin="4,0"/> </WrapPanel> </WrapPanel> <TextBlock HorizontalAlignment="Right" Foreground="Black" Margin="4,2" FontSize="16"> <Run Text="Count:"></Run> <Run Text="{Binding ElementName=DocumentsList,Path=.Items.Count,Mode=OneTime}"></Run> </TextBlock> <ListBox x:Name="DocumentsList" ItemsSource="{Binding Source={StaticResource myHospitalList}}" Margin="0,24,0,0"> <ListBox.ItemTemplate> <DataTemplate> <Border BorderBrush="{Binding State,Converter={StaticResource stateConvert}}" BorderThickness="1" Width="196" Height="94"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Rectangle Fill="{Binding State,Converter={StaticResource stateConvert}}" Opacity=".2" Grid.ColumnSpan="2" Grid.RowSpan="3"/> <Border Grid.RowSpan="2" Grid.Column="0" Width="60" Height="60" Margin="0,4,0,0" CornerRadius="10"> <Border.Background> <ImageBrush ImageSource="{Binding UserImage}" Stretch="Uniform"/> </Border.Background> </Border> <TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding Path=Id}" Margin="0,4,0,0"/> <TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding Path=DoctorName}"/> <TextBlock Grid.ColumnSpan="2" Grid.Row="2" Padding="10,0" Text="{Binding Path=HospitalName}" TextTrimming="CharacterEllipsis"/> </Grid> </Border> </DataTemplate> </ListBox.ItemTemplate> <ListBox.Template> <ControlTemplate> <Border CornerRadius="2" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <ScrollViewer x:Name="ScrollViewer" Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}" BorderBrush="Transparent" BorderThickness="0" IsTabStop="False"> <ItemsPresenter /> </ScrollViewer> </Border> </ControlTemplate> </ListBox.Template> <ListBox.ItemsPanel> <ItemsPanelTemplate> <ws:VirtualizingWrapPanel ItemWidth="200" ItemHeight="100"/> </ItemsPanelTemplate> </ListBox.ItemsPanel> </ListBox> </Grid> </ws:Window>
4) 状态StateConvert.cs如下:
using System; using System.Windows.Data; using System.Windows.Media; namespace WPFDevelopers.Minimal.Sample.Converts { public class StateConvert : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo cultureInfo) { var color = Brushes.Green; if (value != null) { var state = int.Parse(value.ToString()); switch (state) { case 0: color = Brushes.Green; break; case 1: color = Brushes.Orange; break; case 2: color = Brushes.Red; break; } } return color; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo cultureInfo) { throw new NotImplementedException(); } } }
实现效果
加载全部内容