C# 从虚拟化派生StackPanel不起作用

C# 从虚拟化派生StackPanel不起作用,c#,wpf,xaml,C#,Wpf,Xaml,我正在尝试创建虚拟化统一网格,所以我从中获取了一些代码,创建了一个面板,可以在其中设置列数, 它工作得很好,大约比标准的统一网格快3-4倍(我在一个复杂的列表框项目模板上测试了它,有很多记录)。 所以我想我把基本控件从一个面板改为另一个面板,但一旦我这样做了,就没有记录显示。你知道为什么吗? 这是我的工作代码: 将以下内容更改为从VirtualzingPanel或VirtualzingStackPanel派生,它将不再工作:( 公共类MyUniformGrid:Panel//virtualzin

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

将以下内容更改为从VirtualzingPanel或VirtualzingStackPanel派生,它将不再工作:(

公共类MyUniformGrid:Panel//virtualzingstackpanel
{
public static readonly dependencProperty ColumnsProperty=dependencProperty.Register(“Columns”、typeof(int)、typeof(MyUniformGrid)、new FrameworkPropertyMetadata(1、FrameworkPropertyMetadata options.AffectsMeasure));
公共int列
{
set{SetValue(ColumnsProperty,value);}
获取{return(int)GetValue(ColumnsProperty);}
}
private int Rows=>(InternalChildren.Count+Columns-1)/Columns;
受保护的覆盖大小测量覆盖(大小大小可用)
{
var sizeChild=新大小(sizeAvailable.Width/列,sizeAvailable.Height/行);
双最大宽度=0;
双最大高度=0;
foreach(InternalChildren中的UIElement子元素)
{
儿童测量(sizeChild);
maxwidth=Math.Max(maxwidth,child.DesiredSize.Width);
maxheight=Math.Max(maxheight,child.DesiredSize.Height);
}
返回新大小(列*最大宽度,行*最大高度);
}
受保护的替代大小ArrangeOverride(大小sizeFinal)
{
var sizeChild=新大小(sizeFinal.Width/列,sizeFinal.Height/行);
对于(var index=0;index
xaml


代码隐藏

    public MainWindow()
    {
        InitializeComponent();
        var list = new List<int>();
        for (int i = 0; i < 1000; i++)
        {
            list.Add(i);
        }
        MyListBox.ItemsSource = list;
    }
public主窗口()
{
初始化组件();
var list=新列表();
对于(int i=0;i<1000;i++)
{
列表.添加(i);
}
MyListBox.ItemsSource=列表;
}

谢谢你

我不是
虚拟化StackPanel
方面的专家,但是如果你只是想解决物品显示问题,下面的方法就行了

 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;
    }
}
公共类MyUniformGrid:VirtualzingStackPanel
{
public static readonly dependencProperty ColumnsProperty=dependencProperty.Register(“Columns”、typeof(int)、typeof(MyUniformGrid)、new FrameworkPropertyMetadata(1、FrameworkPropertyMetadata options.AffectsMeasure));
公共int列
{
set{SetValue(ColumnsProperty,value);}
获取{return(int)GetValue(ColumnsProperty);}
}
私有整数行
{
得到
{                
返回(InternalChildren.Count+Columns-1)/列;
}
}
受保护的覆盖大小测量覆盖(大小大小可用)
{
基本测量值(可用尺寸);
var sizeChild=新大小(sizeAvailable.Width/列,sizeAvailable.Height/行);
双最大宽度=0;
双最大高度=0;
foreach(此.InternalChildren中的UIElement子元素)
{
儿童测量(sizeChild);
maxwidth=Math.Max(maxwidth,child.DesiredSize.Width);
maxheight=Math.Max(maxheight,child.DesiredSize.Height);
}
返回新大小(列*最大宽度,行*最大高度);
}
受保护的替代大小ArrangeOverride(大小sizeFinal)
{
base.ArrangeOverride(sizeFinal);
var sizeChild=新大小(sizeFinal.Width/列,sizeFinal.Height/行);
对于(var index=0;index

但是
虚拟化StackPanel
是一个非常复杂的实现,然后
覆盖
度量覆盖
安排覆盖
方法和安排项目。您需要处理滚动信息,并且需要处理面板中项目的添加和删除。因此,即使在完全显示项目之后您可能无法获得所需的性能。

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

风格

<!--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



您还应该能够为
WrapPanel
设置样式,以便从中获得任何其他性能提升。

这是因为实现自定义虚拟化面板并不像从VirtualzingPanel继承那么简单。请参见此处的自定义虚拟化面板示例:@Evk谢谢您的评论,我认为会的简单一点,因为如果我简单地将ItemsPanelTemplate更改为VirtualzingStackPanel,它工作得很好,但显然我没有得到列。因此,如果这个虚拟化面板是开箱即用的,我不理解它是如何工作的,当从ITVirtualzingPanel派生时,VirtualzingPanel是抽象类,因此它不能开箱即用,您必须添加安一
 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;
    }
}
<!--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-->
<ListBox x:Name="MyListBox" Style="StaticResource ListBox_HorizontalWrapStyle">