首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从VirtualizingStackPanel派生不起作用

从VirtualizingStackPanel派生不起作用
EN

Stack Overflow用户
提问于 2016-05-04 16:13:31
回答 2查看 344关注 0票数 1

我正在尝试创建虚拟化的统一网格,所以我从here中获取了一些代码,它创建了一个面板,我可以在其中设置列数,它工作得很好,它比标准的统一网格快3-4倍(我在一个包含许多记录的列表框的复杂项目模板上测试了它)。所以我想我把基本控件从面板改成了VirtualizingStackPanel,但是一旦我这样做了,就没有记录显示。你知道为什么吗?以下是我的工作代码:

在下面更改为从VirtualizingPanel或VirtualizingStackPanel派生,它将不再起作用:(

代码语言:javascript
复制
public class MyUniformGrid : Panel // VirtualizingStackPanel
{
    public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register("Columns", typeof(int), typeof(MyUniformGrid), new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.AffectsMeasure));

    public int Columns
    {
        set { SetValue(ColumnsProperty, value); }
        get { return (int)GetValue(ColumnsProperty); }
    }

    private int Rows => (InternalChildren.Count + Columns - 1) / Columns;

    protected override Size MeasureOverride(Size sizeAvailable)
    {
        var sizeChild = new Size(sizeAvailable.Width / Columns, sizeAvailable.Height / Rows);

        double maxwidth = 0;
        double maxheight = 0;

        foreach (UIElement child in InternalChildren)
        {
            child.Measure(sizeChild);

            maxwidth = Math.Max(maxwidth, child.DesiredSize.Width);
            maxheight = Math.Max(maxheight, child.DesiredSize.Height);
        }
        return new Size(Columns * maxwidth, Rows * maxheight);
    }

    protected override Size ArrangeOverride(Size sizeFinal)
    {
        var sizeChild = new Size(sizeFinal.Width / Columns, sizeFinal.Height / Rows);
        for (var index = 0; index < InternalChildren.Count; index++)
        {
            var row = index / Columns;
            var col = index % Columns;
            var rectChild = new Rect(new Point(col * sizeChild.Width, row * sizeChild.Height), sizeChild);

            InternalChildren[index].Arrange(rectChild);
        }
        return sizeFinal;
    }
}

xaml

代码语言:javascript
复制
<ListBox x:Name="MyListBox">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <uniformGridDemo:MyUniformGrid Columns="2" />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

代码隐藏

代码语言:javascript
复制
    public MainWindow()
    {
        InitializeComponent();
        var list = new List<int>();
        for (int i = 0; i < 1000; i++)
        {
            list.Add(i);
        }
        MyListBox.ItemsSource = list;
    }

谢谢

EN

回答 2

Stack Overflow用户

发布于 2016-05-08 00:03:02

我不是VirtualizingStackPanel方面的专家,但如果你只是想解决项目显示问题,下面的方法就行了。

代码语言:javascript
复制
 public class MyUniformGrid :  VirtualizingStackPanel
{
    public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register("Columns", typeof(int), typeof(MyUniformGrid), new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.AffectsMeasure));

    public int Columns
    {
        set { SetValue(ColumnsProperty, value); }
        get { return (int)GetValue(ColumnsProperty); }
    }

    private int Rows
    {
        get
        {                
            return (InternalChildren.Count + Columns - 1) / Columns;
        }
    }

    protected override Size MeasureOverride(Size sizeAvailable)
    {
        base.MeasureOverride(sizeAvailable);
        var sizeChild = new Size(sizeAvailable.Width / Columns, sizeAvailable.Height / Rows);

        double maxwidth = 0;
        double maxheight = 0;

        foreach (UIElement child in this.InternalChildren)
        {
            child.Measure(sizeChild);

            maxwidth = Math.Max(maxwidth, child.DesiredSize.Width);
            maxheight = Math.Max(maxheight, child.DesiredSize.Height);
        }
        return new Size(Columns * maxwidth, Rows * maxheight);

    }

    protected override Size ArrangeOverride(Size sizeFinal)
    {
        base.ArrangeOverride(sizeFinal);
        var sizeChild = new Size(sizeFinal.Width / Columns, sizeFinal.Height / Rows);
        for (var index = 0; index < InternalChildren.Count; index++)
        {
            var row = index / Columns;
            var col = index % Columns;
            var rectChild = new Rect(new Point(col * sizeChild.Width, row * sizeChild.Height), sizeChild);

            InternalChildren[index].Arrange(rectChild);
        }
        return sizeFinal;
    }
}

但是VirtualizingStackPanel的实现要比overridingMeasureOverrideArrangeOverride方法和安排项复杂得多。您需要处理滚动信息,并且需要处理面板中项目的添加和删除。因此,即使在完全显示项目之后,您也可能无法获得所需的性能。

票数 1
EN

Stack Overflow用户

发布于 2016-05-12 10:05:58

我在Silverlight中实现了类似的功能,将样式应用到ListBox,并用WrapPanel替换了ItemsPanelTemplate。我已经在Windows Phone和WPF项目中使用了相同的方法,没有出现任何问题。

样式

代码语言:javascript
复制
<!--Wrapping ListBox Styles-->
<Style x:Key="StretchedItemContainerStyle" TargetType="ListBoxItem">
    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>

<Style x:Key="ListBox_HorizontalWrapStyle" TargetType="ListBox">
    <Setter Property="ItemContainerStyle" Value="{StaticResource StretchedItemContainerStyle}"/>
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Horizontal" Margin="0"/>
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBox">
                <ScrollViewer VerticalScrollBarVisibility="Auto" BorderBrush="{x:Null}" >
                    <ItemsPresenter />
                </ScrollViewer>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<!--End Wrapping ListBox Styles-->

Xaml

代码语言:javascript
复制
<ListBox x:Name="MyListBox" Style="StaticResource ListBox_HorizontalWrapStyle">

您还应该能够设置WrapPanel的样式,以获得任何其他性能收益。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37022060

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档