Followed by the copy of the blog on http://bea.stollnitz.com/blog/?p=338 (with title of UI Virtualization), Joe has created his own blog with some connotation.
The article from the original post does not include the code, in this blog, I have implemented some code which can demonstrate the use of the technique that has been inroduced.
In summary, the following technique has been inroduced
- VirtualizingStackPanel to ItemsPaneTemplate
- Container Recycling
- Deferred Scrolling
- UI Virtualizing extended to Hierarchical Data structure, such as the TreeView
Below shows the Xaml definition and the code behind source code (in C#)
The xaml code
<Window x:Class="Virtualization.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Virtualization"
Title="MainWindow" Height="650" Width="700"
>
<!-- this template is copying from the twiki of
http://vbcity.com/blogs/xtab/archive/2009/11/25/wpf-how-to-list-select-and-apply-fonts.aspx
with the title of
WPF: How To List, Select and Apply Fonts
-->
<Window.Resources>
<DataTemplate x:Key="FontDisplay">
<TextBlock Text="{Binding}"
FontFamily="{Binding}" FontSize="14" />
</DataTemplate>
</Window.Resources>
<StackPanel>
<!-- the ComboBox that has no data virtualization -->
<ComboBox x:Name="CombFonts"
ItemsSource="{Binding}"
Margin="4,22,9,27"
ItemTemplate="{StaticResource FontDisplay}"
>
</ComboBox>
<Separator />
<TextBlock Margin="6,10, 0, 1" Text="Combo with VirualizingStackPanel as ComboBox.ItemsPanel" HorizontalAlignment="Left" VerticalAlignment="Center" FontWeight="Bold" />
<!--
-->
<ComboBox
x:Name="CombFonts2"
ItemsSource="{Binding}"
Margin="4,22,9,27"
ItemTemplate="{StaticResource FontDisplay}"
>
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
<Separator />
<TextBlock Margin="6,10, 0, 1" Text="ListBox with Container recyling" HorizontalAlignment="Left" VerticalAlignment="Center" FontWeight="Bold" />
<!-- the following demonstrate the use of the VirtualizingMode in VirtualizingStackPanel
The comment is based on the article
http://bea.stollnitz.com/blog/?p=338
section
Container recycling
the principle/foundation of the Container recycle is as follow.
30 ListBoxItems are created to display the visible data. When the user scrolls the ListBox, instead of discarding ListBoxItems that scroll out of view and creating new ones for the data items that scroll into view, WPF reuses the existing ListBoxItems, So basically it is the ListBoxItems reuse.
There are two values of the VirtualizationMode, they are
* Recyling
* Standard
To maintain the backword compatibility with the behavior of the earlier versions, container recycling is disable by default (the default VirtualizationMode is "Standard")
-->
<ListBox
VirtualizingStackPanel.VirtualizationMode="Recycling"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource FontDisplay}"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
Height="100"
>
</ListBox>
<Separator />
<TextBlock Margin="6,10, 0, 1" Text="ListBox with Defered Scrolling" HorizontalAlignment="Left" VerticalAlignment="Center" FontWeight="Bold" />
<!--
“Deferred scrolling” is a feature that allows the user to drag the scroll bar thumb around without changing the displayed items until the scroll bar thumb is released.
-->
<ListBox ScrollViewer.IsDeferredScrollingEnabled="True"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource FontDisplay}"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
Height="100" />
<Separator />
<TextBlock Margin="6,10, 0, 1" Text="Hierarchical Data with IsVirtualizing=True" HorizontalAlignment="Left" VerticalAlignment="Center" FontWeight="Bold" />
<!--
Since the advent of .NET framework 3.5, the team has added the Virutalization Support to the Hierarchical structure, such as the TreeView
So use the virtualization, you can need to do is to set the following tags
VirtualizingStackPanel.IsVirtualizing="True"
But if you want to have more control on the Data virtualization, I would suggest you take a look at the example of TreeView3
-->
<TreeView
ItemsSource="{Binding Path=RootKeys}"
VirtualizingStackPanel.IsVirtualizing="True"
x:Name="TreeViewRegistry"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
Height="100"
>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:RegistryKeyHolder1}"
ItemsSource="{Binding Path=SubKeys}">
<TextBlock Text="{Binding Path=ShortName}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</StackPanel>
</Window>
The C# code
using System;
using System.Collections.Generic;
using System.Linq;
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;
using System.Security.Permissions;
using System.Security;
using System.Collections.ObjectModel;
using Microsoft.Win32;
namespace Virtualization
{
[assembly: RegistryPermissionAttribute(SecurityAction.RequestMinimum, Read = "HKEY_CURRENT_CONFIG")]
[assembly: RegistryPermissionAttribute(SecurityAction.RequestMinimum, Read = "HKEY_CURRENT_USER")]
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InitializeDataContextToSystemFonts();
InitializeTreeViewDataSourceToRegistries();
}
private void InitializeDataContextToSystemFonts()
{
this.DataContext = Fonts.SystemFontFamilies;
}
private void InitializeTreeViewDataSourceToRegistries()
{
this.TreeViewRegistry.DataContext = new RegistryData1();
}
}
#region TreeView Data
// this TreeView data is copied from the previous example on the TreeViews.
// since we want to make the TreeView simple, so we take the example from
// TreeView1. which does not have UI Virtualization and no DataVirtualization
//
#region Data - No UI visualization, no data virtualization
public class RegistryData1
{
private ObservableCollection<RegistryKeyHolder1> rootKeys;
private int dataItemsCount;
/// <summary>
/// The root keys, such as HKEY_CURRENT_CONFIG, or HKEY_CURRENT_USER
/// </summary>
public ObservableCollection<RegistryKeyHolder1> RootKeys
{
get { return rootKeys; }
}
/// <summary>
/// Total number of items that has been populated
/// </summary>
public int DataItemsCount
{
get { return dataItemsCount; }
}
public RegistryData1()
{
this.rootKeys = new ObservableCollection<RegistryKeyHolder1>();
rootKeys.Add(new RegistryKeyHolder1(Registry.CurrentUser));
rootKeys.Add(new RegistryKeyHolder1(Registry.CurrentConfig));
this.dataItemsCount = 2;
PopulateSubKeys(this.rootKeys);
}
private void PopulateSubKeys(ObservableCollection<RegistryKeyHolder1> keys)
{
foreach (RegistryKeyHolder1 keyHolder in keys)
{
// expand each of the subkeys
keyHolder.PopulateSubKeys();
this.dataItemsCount += keyHolder.SubKeys.Count;
// set a hard limit so that we don't blow
if (this.dataItemsCount >= 5000)
{
return;
}
PopulateSubKeys(keyHolder.SubKeys);
}
}
}
/// <summary>
/// Registry Key Holder
/// </summary>
public class RegistryKeyHolder1
{
private RegistryKey key;
private ObservableCollection<RegistryKeyHolder1> subKeys;
public RegistryKey Key
{
get { return key; }
}
public string ShortName
{
get { return key.Name.Substring(key.Name.LastIndexOf('\\') + 1); }
}
public ObservableCollection<RegistryKeyHolder1> SubKeys
{
get { return subKeys; }
}
public RegistryKeyHolder1(RegistryKey key)
{
this.key = key;
this.subKeys = new ObservableCollection<RegistryKeyHolder1>();
}
/// <summary>
/// Populate <paramref name="this"/> SubKeys collection
/// </summary>
/// <remarks>
/// Lazy populate the subkeys </remarks>
public void PopulateSubKeys()
{
try
{
string[] subKeyNames = this.key.GetSubKeyNames();
for (int i = 0; i < subKeyNames.Length; ++i)
{
this.subKeys.Add(new RegistryKeyHolder1(this.key.OpenSubKey(subKeyNames[i])));
}
}
catch (SecurityException ex)
{
System.Console.WriteLine(ex.Message);
}
}
}
#endregion Data - No UI visualization, no data virtualization
#endregion TreeView Data
}
and below shows the snapshot of the application in action.

WPF UI虚拟化技术
本文介绍了WPF中UI虚拟化的几种技术,包括使用VirtualizingStackPanel进行虚拟化、容器回收、延迟滚动以及如何将这些技术应用于层次数据结构如TreeView等。
164

被折叠的 条评论
为什么被折叠?



