WPF – Virtualization – VirutalizationStackPanel and ItemsPanelTemplate

Topic: WPF – Virtualization – VirutalizationStackPanel and ItemsPanelTemplate

标题: WPF – 控件虚拟化- 简单介绍VirutalizationStackPanel和ItemsPanelTemplate

在ItemsPanel上的虚拟化, 你可以使用VirutalizationStackPanel, 和 “ItemsPanelTemplate”, 以下是一个虚拟化的例子.

Virtualization on the ItemsPanel, you can use the VirutalizationStackPanel, together with the “ItemsPanelTemplate”, here is a live use example of that .

                <cn:CustomListView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel
                            cmbh:PixelBasedScrollingBehavior.IsEnabled="True"
                            VirtualizationMode="Recycling"/>
                    </ItemsPanelTemplate>
                </cn:CustomListView.ItemsPanel>

 

我们将关注两点,一点是VirtualizingStackPanel,另一点是ItemsPanelTemplate

So we will focus on two parts, one is the VirtualizingStackPanel and the other is ItemsPanelTemplate

 

VirtualizingStackPanel

一般的来说,标准的布局系统为每一个元素创建元素容器和布局元素,虚拟化这个词的意思是指一种从大量的数据中,只显示用户界面可见一部分元素的技巧。如果只有少量的元素被显示,但生成许多UI元素的做法会影响到他的performance. VirtualizingStackPanel计算,控制ItemsControl (比如说ListBox 或ListView)的ItemContainerGenerator生成可视部分元素。

So generally, the standard layout system create item containers and layout for each item associate with a list control, the word “virtualize” refers to a technique by which a subset of user interface (UI) elements are generated from a larger number of data items based on which items are visible on-screen. Generating many UI elements when only a few elements might be on the screen can adversely affect the performance of your application. The VirtualizingStackPanel calculates the number of visible items and works with the ItemContainerGenerator from an ItemsControl (such as ListBox or ListView) to create UI elements only for Visible items.

 

虚拟化只是在panel里面的items control生成自己的item container.可以采用数据绑定的办法确保如此。如果item container是被显示的创立的话,那么virtualizingStackPanel比没用virtualizingStackPanel没有效率的优势。

Virtualization in a StackPanel only occurs when the items control contained in the panel creates its own item container. You can ensure this happen by using DataBinding . In Scenarios where item container are created and added to the items control. A virtualizingStackPanel offers no performance advantage over a StackPanel.

 

VirtualizingStackPanel是ListBox元素的默认元素容器,默认的,IsVirtualizing属性值是true.

VirtualizingStackPanel is the default items host for ListBox element, by default, the IsVirtualizing property is set to true.

 

IsVirtualizing属性值是false时,和不用VirtualizingStackPanel效果是一样的。

When isVirtualizing is set to false, a VirtualizingStackPanel behaves the same as an ordinary StackPanel.

 

如下所例,用IsVirtualizing这个attached属性,我们可以控制ListBox的虚拟化。

So an example of such, with the attached property, IsVirtualizing, you can Virtualizing on ListBox as such ..

 

<Page x:Class="DemoVirtualizingStackPanel.ListboxVirutalizationPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="ListboxVirutalizationPage"
      VerticalAlignment="Top"
      >
    <Page.Resources>
        <XmlDataProvider x:Key="Leagues" Source="Leagues.xml" XPath="Leagues/League" />
       
        <DataTemplate
            x:Key="NameDataStyle"
            >
            <TextBlock
                Text="{Binding XPath=@name}"
                FontFamily="Arial"      
                FontSize="8"
                Foreground="Black"
                       >
            </TextBlock>
        </DataTemplate>
    </Page.Resources>
   
   
    <Border
        HorizontalAlignment="Left"
        VerticalAlignment="Top"
        BorderBrush="Black"
        BorderThickness="2">
        <StackPanel
            DataContext="{StaticResource Leagues}"
            >
            <TextBlock
                Text="{Binding XPath=@name}"
                FontFamily="Arial"
                FontSize="18"
                Foreground="Black"
                ></TextBlock>
        <ListBox
            VirtualizingStackPanel.IsVirtualizing="True"
            ItemsSource="{Binding XPath=Team}"
            ItemTemplate="{DynamicResource NameDataStyle}"
            ></ListBox>
        </StackPanel>
    </Border>
</Page>

 

可以进一步的控制VirtualizationMode,值Recycling和Standard。

You can further control the VirtualizationMode, possible value are Recycling and Standard.

<Page x:Class="DemoVirtualizingStackPanel.RecyclingVirtualizationPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:src="clr-namespace:DemoVirtualizingStackPanel.ViewModels"
      Title="RecyclingVirtualizationPage">
 
   <StackPanel>
       <StackPanel.Resources>
           <src:LotsOfItems x:Key="data" />
       </StackPanel.Resources>
       <ListBox
           Height="150"
           ItemsSource="{StaticResource data}"
           VirtualizingStackPanel.VirtualizationMode="Recycling"
           ></ListBox>
   </StackPanel>
</Page>

 如果你感兴趣的话,ViewModel定义如下:

For your interest, the ViewModel is like this:

 

        public class LotsOfItems : ObservableCollection<string>
        {
             public LotsOfItems()
             {
                 for (int i = 0; i < 1000; i++)
                     this.Add("Item " + i.ToString());
             }
        }
 

 

Xml provider的数据xml如下:

And the Xml that provides the data is like this:

// Leagues.xml
<?xml version="1.0" encoding="utf-8" ?>
<Leagues>
  <League name="England League">
    <Team name="Liz"  />
    <Team name="Liverpool"  />
    <Team name="Manchester Union" />
    <Team name="Charls" />
    <Team name="Arsenal" />
    <Team name="Mancester City" />
    <Team name="New Castle" />
    <Team name="Cambridge U" />
    <Team name="Oxford U" />
    <Team name="East London" />
  </League>
</Leagues>

 

ItemsPanelTemplate

在我们看到的第一个例子中,要介绍的第二个元素是“ItemsPanelTemplate”.

 

And in the first example that we introduced, the second items that we may use is the “ItemsPanelTemplate”.

ItemsPanelTemplate定义了作为布局元素的panel,GroupStyle有一个panel属性,他的类型是ItemsPanelTemplate,ItemsControl类型有一个ItemsPanel属性,值是ItemsPanelTemplate.每一个ItemsControl有一个默认的ItemsPanel类型,ItemsControl的ItemsPanel是StackPanel, ListBoxItemsPanel是VirtualizingStackPanel,MenuItem的值是WrapPanel,Status的为DockPanel.

 

The ItemsPanelTemplate specifies the panel that is used for the layout of items. GroupStyle has a Panel property that is of type ItemsPanelTemplate.ItemsControl types have an ItemsPanel property that is of type ItemsPanelTemplate.

Each ItemsControl type has a default ItemsPanelTemplate. For the ItemsControl class, the default ItemsPanel value is an ItemsPanelTemplate that specifies aStackPanel. For the ListBox, the default uses the VirtualizingStackPanel. For MenuItem, the default uses WrapPanel. For StatusBar, the default usesDockPanel.

 

下面的例子中,我们将要介绍几种创建vertical ListBox的方法。

In the following examples. We will introduce ways to create Vertical ListBox.

 

例子1 – ItemsPanel 属性

 

Example 1 – With the ItemsPanel property

        <Style TargetType="ListBox"
               >
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <StackPanel
                            Orientation="Horizontal"
                            VerticalAlignment="Center"
                            HorizontalAlignment="Center"></StackPanel>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
        </Style>

 

装配起来,我们定义了“DataTemplate” and the “XmlDataProvider”,整体的代码如下:

To wire it up, we defined the “DataTemplate” and the “XmlDataProvider”. The overall code is as follow.

<Page x:Class="DemoItemsPanelTemplate.HorizontalListBoxPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="HorizontalListBoxPage">
    <Page.Resources>
        <XmlDataProvider x:Key="Leagues" Source="Leagues.xml" XPath="Leagues/League" />
        <DataTemplate
            x:Key="NameDataStyle"
            >
            <TextBlock
                Text="{Binding XPath=@name}"
                FontFamily="Arial"      
                FontSize="8"
                Foreground="Black"
                       >
            </TextBlock>
        </DataTemplate>
       
        <Style TargetType="ListBox"
               >
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <StackPanel
                            Orientation="Horizontal"
                            VerticalAlignment="Center"
                            HorizontalAlignment="Center"></StackPanel>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Page.Resources>
    <Grid>
        <!-- style is the default Style specified in the Page.Resources -->
        <ListBox
            DataContext="{StaticResource Leagues}"
            ItemsSource="{Binding XPath=Team}"
            ItemTemplate="{DynamicResource NameDataStyle}"
            ></ListBox>
    </Grid>
</Page>
 

 

在后面的例子中,我们将复用ListBox, XmlDataProvider 和DataTemplate定义。

 

We will reuse the ListBox, XmlDataProvider and DataTemplate definition in following examples.

 

例子2

Example 2

除了使用ItemsPanelTemplate,在下面的例子中,我们再ControlTemplate里定义了一个horizontal stackpanel,请注意,我们使用了IsItemsHost属性,表示生成的元素将到这个StackPanel里面去。

Instead of using the ItemsPanelTemplate, in this example, we specify a horizontal stackpanel within the ControlTemplate, note that we uses IsItemsHost property of the StackPanel, indicating that the generated items should go in the panel..

 

这个方法的不足是,我们不替换ControlTemplate就不能替换ItemsPanelTemplate。Style的定义如下

The drawback is user cannot replace the ItemsPanelTemplate without using a ControlTemplate. So using this technique with care.

Style definition is as follow.

    <Style TargetType="ListBox">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBox">
                    <Border
                            CornerRadius="5"
                            Background="{TemplateBinding ListBox.Background}">
                        <ScrollViewer
                                HorizontalScrollBarVisibility="Auto">
                            <StackPanel
                                    Orientation="Horizontal"
                                    VerticalAlignment="Center"
                                    HorizontalAlignment="Center"
                                    IsItemsHost="True"
                                    >
                            </StackPanel>
                        </ScrollViewer>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
 

 

例子3

Example 3:

我们可以同时替换ItemsPanel和Control Template,代码如下:

We can alternatively replace both the ItemsPanel and the Control Template, code as follow.

 

    <Style
        TargetType="{x:Type ListBox}">
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <StackPanel
                        Orientation="Horizontal"
                        VerticalAlignment="Center"
                        HorizontalAlignment="Center"></StackPanel>
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate
                    TargetType="{x:Type ListBox}"
                    >
                    <Border
                        CornerRadius="5"
                        Background="{TemplateBinding ListBox.Background}">
                        <ScrollViewer
                            HorizontalScrollBarVisibility="Auto">
                            <ItemsPresenter /> <!-- The ItemsPresenter creates the Panels for the layout ofr hte Items based on what is specified by the ItemsPanelTemplate -->
                        </ScrollViewer>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
 
 

 

主函数如下

In general, the Main code is as such

        [STAThread]
        [DebuggerNonUserCode]
        public static void Main(string[] args)
        {
            App app = new App();
            //app.InitializeComponent();
            app.Run(new MainWindow());
        }

 在主窗口的 代码种,加入如下的Page代码(ListBox写在Page里面).

And in the MainWindow, do things like this for the pages that contains the ListBox with Customizing Styles.

 

    <page:HorizontalListBoxPage
        VerticalAlignment="Stretch"
        HorizontalAlignment="Stretch"
        Height="300"
        Width="450"
        xmlns:page="clr-namespace:DemoItemsPanelTemplate"
        ></page:HorizontalListBoxPage>

 

Or

    <page:HorizontalLisBoxWithControlTemplatePage
        VerticalAlignment="Center"
        HorizontalAlignment="Center"
        Height="300"
        Width="450"
        xmlns:page="clr-namespace:DemoItemsPanelTemplate"></page:HorizontalLisBoxWithControlTemplatePage>
   

 

Or

 

   <page:ControlAndItemsPanelTemplatePage
        VerticalAlignment="Center"
        HorizontalAlignment="Center"
        Height="300"
        Width="450"
        xmlns:page="clr-namespace:DemoItemsPanelTemplate"
        ></page:ControlAndItemsPanelTemplatePage>

 

引用:

References:

VirtualizationStackPanel Class

ItemsPanelTemplate

VirtualizationMode Enumeration

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值