如何按最大项目设置GridView项目大小
我试图在如何按最大项目设置GridView项目大小,gridview,windows-store-apps,Gridview,Windows Store Apps,我试图在网格视图中显示多个项目。它之所以被选中,主要是因为它的水平滚动行为 它看起来像是GridView根据第一个项目维度定义项目大小。在下面的代码示例中,如果年份从1月开始,则会裁剪较长的月份名称,但如果第一项较宽,则会按预期显示名称 我确实想保持GridView所有项目的宽度相同,但这必须是最大项目的宽度。高度也是一样,但在我的例子中,高度是恒定的 使用GridView是否有相对简单的方法来实现这一点,或者是否有更合适的控件来实现这一点 一月 二月 ... 九月 十月 十一月 十二月
网格视图中显示多个项目。它之所以被选中,主要是因为它的水平滚动行为
它看起来像是GridView
根据第一个项目维度定义项目大小。在下面的代码示例中,如果年份从1月开始,则会裁剪较长的月份名称,但如果第一项较宽,则会按预期显示名称
我确实想保持GridView
所有项目的宽度相同,但这必须是最大项目的宽度。高度也是一样,但在我的例子中,高度是恒定的
使用GridView
是否有相对简单的方法来实现这一点,或者是否有更合适的控件来实现这一点
一月
二月
...
九月
十月
十一月
十二月
注意:对于不同/可变的物品尺寸,有多个例子。不幸的是,这不是必需的。经过一些研究,满足需求的最简单方法是在ItemsPanelTemplate
中使用自定义面板
一些被拒绝的方法是
1) 扩展GridView
:当开发人员从GridView派生出大量有趣的信息时,实际的布局管理是在GridView中执行的。ItemsPanel
控制和修改项目在其外部的位置需要许多黑客或脆弱的设计决策。
2) 扩展现有的ItemPanel
容器:这将是最自然的方法,但是由于像WrapGrid
或VariableSizedWrapGrid
这样的类是密封的,这是不可能的
下面是一个将自定义面板与GridView
一起使用的示例
如果项目太少,无法填充整个网格视图,对齐设置会将项目放置在左上角而不是中间位置
边距补偿滚动条重叠内容的默认行为
<GridView ... >
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<controls:GridViewPanel
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="0,0,0,24" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
...
</GridView>
您可以创建一个自定义的GridView
类(仅从基GridView
继承),该类覆盖ArrangeOverride
。在安排项目时,首先它会测量所有项目(一次不能测量一个),并根据项目中最大的项目选择项目大小。@Nate Diamond谢谢,但您能否进一步阐述1-2个步骤?我询问的原因是,在调用ArrangeOverride
期间重新安排项目将导致递归布局更新,几乎可以保证异常。此外,如果我朝这个方向走,那么定制ItemsPanel
容器而不是GridView
可能是有意义的。我不一定要重新安排它们。ArrangeOverride应在每个子项上调用arrange,传递该项将要给定的空间量。因此,这意味着它应该能够搜索项目的度量值
(而不仅仅是使用第一个项目),并找到其中最大的一个。的确,这可以通过面板来实现,比如定制VariableSizeWrapGrid
;除非我遗漏了什么,否则就没有关于GridView
如何定位单个项目的信息:在这一点上,如果您谈论派生类,那么GridView
是一个黑框。不过我知道你的想法了,谢谢。这是有道理的,但仍需要更多的步骤。目前,我使用的解决方法是:继承GridView
,在调用MeasureOverride
和ArrangeOverride
之前的某个时间对所有项目运行Measure()
,获得最大DesiredSize
,将其作为DP公开,并将项目的最小宽度、最小高度绑定到该值。
<GridView ... >
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<controls:GridViewPanel
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="0,0,0,24" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
...
</GridView>
using System;
using Windows.Foundation;
using Windows.UI.Xaml.Controls;
/// <summary>
/// Uniformly positions child items in columns to present in WrapGrid.
/// Uses largest item's DesiredSize for item size mesasurements.
/// Expects limited height and unbound width.
/// </summary>
public class GridViewPanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
return ArrangeInternal(availableSize, callArrange: false);
}
protected override Size ArrangeOverride(Size finalSize)
{
return ArrangeInternal(finalSize);
}
private Size ArrangeInternal(Size size, bool callArrange = true)
{
// measure max desired item size
//
double itemWidth = 0.0, itemHeight = 0.0;
foreach (var item in Children)
{
item.Measure(size);
itemWidth = Math.Max(itemWidth, item.DesiredSize.Width);
itemHeight = Math.Max(itemHeight, item.DesiredSize.Height);
}
// requested item height can't exceed total available height
itemHeight = Math.Min(itemHeight, size.Height);
// position each child and get total content size
//
double totalWidth = 0.0, totalHeight = 0.0;
double x = 0.0, y = 0.0;
foreach (var item in Children)
{
if (y + itemHeight > size.Height)
{
// if item won't fit, move to the next column
totalHeight = Math.Max(totalHeight, y);
y = 0;
x += itemWidth;
}
// implicitly, item fits in current column
if (callArrange) item.Arrange(new Rect(x, y, itemWidth, itemHeight));
y += itemHeight;
}
totalWidth = x + itemWidth;
totalHeight = Math.Max(totalHeight, y);
return new Size(totalWidth, totalHeight);
}
}