我正在尝试创建虚拟统一网格,所以我从here中获取了一些代码,创建了一个可以设置列数的面板, 并且它工作正常,它比标准统一网格快3-4倍(我在列表框的复杂项目模板上测试它有很多记录)。 所以我想我将基本控件从Panel更改为VirtualizingStackPanel,但是一旦我这样做,就没有记录显示。任何想法为什么? 这是我的工作代码:
更改以下内容以从VirtualizingPanel或VirtualizingStackPanel派生,它将不再起作用:(
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
<ListBox x:Name="MyListBox">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<uniformGridDemo:MyUniformGrid Columns="2" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
背后的代码
public MainWindow()
{
InitializeComponent();
var list = new List<int>();
for (int i = 0; i < 1000; i++)
{
list.Add(i);
}
MyListBox.ItemsSource = list;
}
谢谢
答案 0 :(得分:0)
我不是VirtualizingStackPanel
的专家,但如果你只想解决项目显示问题,下面就行了。
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
是一个非常复杂的实现,然后是overriding
MeasureOverride
&amp; ArrangeOverride
方法和安排项目。你需要处理滚动信息并尊重那个添加&amp;需要处理面板中的物品移除。因此,即使完全显示项目后,您也可能无法获得所需的性能。
答案 1 :(得分:0)
我已经在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
<ListBox x:Name="MyListBox" Style="StaticResource ListBox_HorizontalWrapStyle">
您还应该能够设定WrapPanel
的样式,以便从中获得其他性能提升。