WPF中实现自定义虚拟容器(实现VirtualizingPanel)
<div id="cnblogs_post_body">在WPF应用程序开发过程中,大数据量的数据展现通常都要考虑性能问题。有下面一种常见的情况:原始数据源数据量很大,但是某一时刻数据容器中的可见元素个数是有限的,剩余大多数元素都处于不可见状态,如果一次性将所有的数据元素都渲染出来则会非常的消耗性能。因而可以考虑只渲染当前可视区域内的元素,当可视区域内的元素需要发生改变时,再渲染即将展现的元素,最后将不再需要展现的元素清除掉,这样可以大大提高性能。在WPF中System.Windows.Controls命名空间下的VirtualizingStackPanel可以实现数据展现的虚拟化功能,ListBox的默认元素展现容器就是它。但有时VirtualizingStackPanel的布局并不能满足我们的实际需要,此时就需要实现自定义布局的虚拟容器了。本文将简单介绍容器自定义布局,然后介绍实现虚拟容器的基本原理,最后给出一个虚拟化分页容器的演示程序。一、WPF中自定义布局 (已了解容器自定义布局的朋友可略过此节)
通常实现一个自定义布局的容器,需要继承System.Windows.Controls.Panel, 并重写下面两个方法:
MeasureOverride &mdash;&mdash; 用来测量子元素期望的布局尺寸
ArrangeOverride &mdash;&mdash; 用来安排子元素在容器中的布局。
下面用一个简单的SplitPanel来加以说明这两个方法的作用。下面的Window中放置了一个SplitPanel,每点击一次&ldquo;添加&rdquo;按钮,都会向SplitPanel中添加一个填充了随机色的Rectangle, 而SplitPanel中的Rectangle无论有几个,都会在垂直方向上布满容器,水平方向上平均分配宽度。
http://images.cnblogs.com/cnblogs_com/talywy/201209/201209072222348191.png
实现代码如下:
<div class="cnblogs_code" >http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gifhttp://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gifSplitPanel <div id="cnblogs_code_open_860f43bc-6b22-42d2-b79a-bcc928f66cd3" class="cnblogs_code_hide"> 1 /// <summary> 2 /// 简单的自定义容器 3 /// 子元素在垂直方向布满容器,水平方向平局分配容器宽度 4 /// </summary> 5 public class SplitPanel : Panel 6 { 7 protected override Size MeasureOverride(Size availableSize) 8 { 9 foreach (UIElement child in InternalChildren)10 {11 child.Measure(availableSize); // 测量子元素期望布局尺寸(child.DesiredSize)12 }13 14 return base.MeasureOverride(availableSize);15 }16 17 protected override Size ArrangeOverride(Size finalSize)18 {19 if (double.IsInfinity(finalSize.Height) || double.IsInfinity(finalSize.Width))20 {21 throw new InvalidOperationException("容器的宽和高必须是确定值");22 }23 24 if (Children.Count > 0)25 {26 double childAverageWidth = finalSize.Width / Children.Count;27 for (int childIndex = 0; childIndex < InternalChildren.Count; childIndex++)28 {29 // 计算子元素将被安排的布局区域30 var rect = new Rect(childIndex * childAverageWidth, 0, childAverageWidth, finalSize.Height);31 InternalChildren.Arrange(rect);32 }33 }34 35 return base.ArrangeOverride(finalSize);36 }37 }
页:
[1]