WrapPanel 实现虚拟化

article/2025/10/25 7:13:05

 WrapPanel 实现虚拟化

控件名:VirtualizingWrapPanel

作者:WPFDevelopersOrg

原文链接:    https://github.com/WPFDevelopersOrg/WPFDevelopers

  • 框架使用大于等于.NET40

  • Visual Studio 2022;

  • 项目使用 MIT 开源许可协议;

  • 众所周知 WPFStackPanel 在加载大量数据时性能会特别差,但是官方提供了一个虚拟化容器VirtualizingStackPanel[1]

    • VirtualizingStackPanel.IsVirtualizing 附加属性设置为 true时就开启虚拟化。

    • VirtualizingStackPanel.IsVirtualizing 附加属性设置为 falseVirtualizingStackPanel行为与普通StackPanel属性的行为相同。

  • WrapPanel 默认是不支持虚拟化的,所以需要自行实现。

1) VirtualizingWrapPanel 查看源码1[2]  |   VirtualizingWrapPanel 查看源码2[3]

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[] { "https://pic2.zhimg.com/80/v2-0711e97955adc9be9fbcff67e1007535_720w.jpg",//"https://pic2.zhimg.com/80/v2-5b7f84c63075ba9771f6e6dc29a54615_720w.jpg","https://pic3.zhimg.com/80/v2-a3d6d8832090520e7ed6c748a8698e4e_720w.jpg","https://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();}}
}
c34387d350a2e01ded2831af0ed23f81.gif

参考资料

[1]

VirtualizingStackPanel: https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.controls.virtualizingstackpanel?view=windowsdesktop-6.0

[2]

VirtualizingWrapPanel 查看源码1: https://github.com/samueldjack/VirtualCollection/blob/master/VirtualCollection/VirtualCollection/VirtualizingWrapPanel.cs

[3]

VirtualizingWrapPanel 查看源码2: https://github.com/WPFDevelopersOrg/WPFDevelopers.Minimal/blob/main/src/WPFDevelopers.Minimal/WPFDevelopers.Minimal.Shared/Controls/VirtualizingWrapPanel/VirtualizingWrapPanel.cs


http://chatgpt.dhexx.cn/article/Vqwas1Ey.shtml

相关文章

对wpf 的入门记录总结----面板控件Canvas、WrapPanel、StackPanel、DockPanel

面板是WPF裡其中一個很重要的控件。 面板扮演著裝載其他控件的容器的角色&#xff0c;同時也控制著頁面和視窗的佈局。 由於一個視窗只允許一個子控件&#xff0c;因此面板經常會被使用於分隔空間&#xff0c;這樣每個空間就會有一個控件或者面板。 wpf支持6种面板&#xff1…

listbox 表头自动换行_WPF让ListView或ListBox中的WrapPanel 自动换行

原文:WPF让ListView或ListBox中的WrapPanel 自动换行 在ListView或者ListBox中使用WrapPanel想让ItemTemplate中的内容像下图这样先横向平铺然后再纵向换行&#xff0c;默认设置是不能实现的。 图1. 横向平铺再纵向换行的效果示例 请注意最关键的在上面代码中第一行的“ScrollV…

WPF教程三:布局之WrapPanel面板(转 )

WPF教程三&#xff1a;布局之WrapPanel面板 WrapPanel&#xff1a;环绕面板 WrapPanel布局面板将各个控件从左至右按照行或列的顺序罗列&#xff0c;当长度或高度不够时就会自动调整进行换行&#xff0c;后续排序按照从上至下或从右至左的顺序进行。 Orientation——根据内容自…

WPF面板布局介绍Grid、StackPanel、DockPanel、WrapPanel

WPF面板布局介绍Grid、StackPanel、DockPanel、WrapPanel 回顾 上一篇&#xff0c;我们介绍了基本控件及控件的重要属性和用法&#xff0c;我们本篇详细介绍WPF中的几种布局容器及每种布局容器的使用场景&#xff0c;当 然这些都是本人在实际项目中的使用经验&#xff0c;可能…

2021-08-16 WPF控件专题 WrapPanel 控件详解

1.WrapPanel 控件介绍 流面板 子元素按顺序排列&#xff0c;如果按水平方向:从左到右&#xff0c;超出部分&#xff0c;自动换行到下一行 垂直 从上到下&#xff0c; 下一列 排列方向&#xff1a;Orientation ItemWidth ItemHeight 调整面板的尺寸时&#xff0c;内部子元素的…

.NET WPF(3)布局之WrapPanel面板

一.WPF&#xff08;3&#xff09;布局之WrapPane面板 1. WrapPanel&#xff1a;环绕面板 WrapPanel布局面板将各个控件从左至右按照行或列的顺序罗列&#xff0c;当长度或高度不够时就会自动调整进行换行&#xff0c;后续排序按照从上至下或从右至左的顺序进行。 Orie…

WPF编程基础入门 ——— 第三章 布局(五)布局面板WrapPanel

WPF布局——布局面板WrapPanel WPF——WrapPanel布局控件WrapPanel实例——十个按钮 WPF——WrapPanel布局控件 WrapPanel(自动折行面板)&#xff0c;允许任意多的子元素按照声明的先后顺序&#xff0c;从左往右摆放&#xff0c;摆满一行后&#xff0c;自动折行。折行面板的经…

WPF布局控件之WrapPanel

WrapPanel WrapPanel&#xff0c;英文意思是折叠容器&#xff0c;那到底是怎么个折叠法呢&#xff1f;如下&#xff1a; <Window x:Class"LearnLayout.WrapPanelWin"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"ht…

.NET WPF教程(7)——布局介绍WrapPanel与StackPanel(②)

三. WrapPanel WrapPanel布局面板将各个控件从左至右按照行或列的顺序罗列&#xff0c;当长度或高度不够是就会自动调整进行换行&#xff0c;后续排序按照从上至下或从右至左的顺序进行。 Orientation——根据内容自动换行。当 Horizontal选项看上去类似于Windows资源管理器…

WPF 用代码实现WrapPanel右侧自动对齐(解决多余空白问题)

未处理前效果&#xff1a; 处理后效果&#xff1a; <Border Background"{StaticResource BorderBg}" BorderThickness"2" BorderBrush"{StaticResource BorderBrush}" CornerRadius"5" Padding"5" x:Name"SvK…

C# Grid StackPanel DockPanel WrapPanel

WPF面板布局介绍Grid、StackPanel、DockPanel、WrapPanel 回顾 上一篇&#xff0c;我们介绍了基本控件及控件的重要属性和用法&#xff0c;我们本篇详细介绍WPF中的几种布局容器及每种布局容器的使用场景&#xff0c;当 然这些都是本人在实际项目中的使用经验&#xff0c;可能…

WPF基础五:UI①布局元素WrapPanel

目录 WrapPanel WrapPanel类 XAML范例&#xff1a; C#代码 WrapPanel 按从左到右的顺序位置定位子元素&#xff0c;在包含框的边缘处将内容切换到下一行。 后续排序按照从上至下或从右至左的顺序进行&#xff0c;具体取决于 Orientation 属性的值。 WrapPanel包含UIElemen…

一个优化奇怪的 WrapPanel

一个优化奇怪的 WrapPanel 本文经原作者授权以原创方式二次分享&#xff0c;欢迎转载、分享。 一个优化奇怪的 WrapPanel 作者&#xff1a;陈-林-赵-魏 原文链接[1]&#xff1a;https://www.cnblogs.com/wandia/p/17092221.html FixToRB 附加属性&#xff0c;固定到【右边(水平…

WPF布局之WrapPanel与StackPanel

转载&#xff1a;https://www.cnblogs.com/Im-Victor/p/10565030.html 三. WrapPanel WrapPanel布局面板将各个控件从左至右按照行或列的顺序罗列&#xff0c;当长度或高度不够是就会自动调整进行换行&#xff0c;后续排序按照从上至下或从右至左的顺序进行。 Orientation——…

WrapPanel在不同页面渲染使用

WrapPanel渲染的使用 WrapPanel在UserControl用户控件的使用 页面控件的是渲染出来&#xff0c;在UserControl用户控件的使用无法直接使用&#xff0c;使用会出现空&#xff0c;没法渲染获取到WrapPanel控件。 没法渲染获取效果图&#xff1a; 想成功获取渲染获取到WrapPane…

WPF 入门教程WrapPanel介绍

WrapPanel将定位每个子控件的旁边&#xff0c;另外&#xff0c;水平方向&#xff08;默认值&#xff09;或垂直&#xff0c;直到没有更多的空间&#xff0c;在那里将换到下一行&#xff0c;然后继续。当您想要一个垂直或水平列表控件在没有更多空间时自动换行时使用它。 当 Wr…

WPF WrapPanel、UniformGrid、DockPanel介绍

WPF WrapPanel、UniformGrid、DockPanel介绍 WrapPanel WrapPanel , 具有在有限的容器范围内, 可以自动换行, 或者换列处理。具体则取决于WrapPanel的排列方式 (Orientation)。 Orientation"Horizontal"时各控件从左至右罗列&#xff0c;当面板长度不够时&#xff…

WPF控件之WrapPanel的用法

简单来说&#xff0c;WrapPanel就是一个可以行填充&#xff0c;自动换行。或者列填充&#xff0c;自动换列的一个布局容器。 如下所示&#xff0c;它会自动将10个button分成2行 <WrapPanel><Button Content"button1" /><Button Content"button…

WrapPanel:自动折行面板(环绕面板)基础简述

WrapPanel布局面板将各个控件从左至右按照行或列的顺序罗列&#xff0c;当长度或高度不够时就会自动调整进行换行或换列&#xff0c;后续排序按照从上至下或从右至左的顺序进行。 Orientation——根据内容自动换行。当Orientation属性的值设置为 Horizontal&#xff1a;元素是…

WPF 控件专题 WrapPanel 控件详解

1、WrapPanel 介绍 官方释义&#xff1a;WrapPanel&#xff08;环绕面板&#xff09;&#xff1a;按从左到右的顺序位置定位子元素&#xff0c;在包含框的边缘处将内容切换到下一行。 后续排序按照从上至下或从右至左的顺序进行&#xff0c;具体取决于 Orientation 属性的值。 …