我的应用程序在使用UniformGrid作为其ItemsPanel的ItemsControl中显示多个项。
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!-- Arrange all items vertically, distribute the space evenly -->
<UniformGrid Columns="1"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>现在,每个项目将占用尽可能多的空间和完整的宽度。事情应该是这样的。但是每一项都不能小于一定的高度,比如250像素。因此,我的ItemsControl被放在一个ScrollViewer中,如果屏幕上的最小高度不再适合,它将开始滚动(但在此之前填充)。
将每一项的MinHeight属性设置为250将使其更高,但不会改变UniformGrid以任何方式排列它们的方式,因此它们将被裁剪。这不是解决方案。
设置整个ItemsControl或UniformGrid的MinHeight属性确实可以,但我需要根据项的数量来计算它。获取更新后的项数的一个好方法是覆盖我的ItemsControl代码隐藏中的OnItemsChanged方法。但这不会给我实际的项目面板。我在另一个项目中有以下代码,但它在这里总是返回null:
ItemsControl itemsControl = ItemsControl.GetItemsOwner(this);因此,这也不起作用。
遍历可视化树可能也不是一个选择,因为为时已晚。我需要在排列项目面板之前设置最小高度,这样它就不会闪烁。(我会在更改大小时生成复杂的内容,因此必须避免任何后期布局。)
我有什么选择才能得到我需要的东西?
如果可能的话,我可能会放弃UniformGrid,转而使用其他东西。有什么建议吗?
发布于 2015-06-03 05:50:56
您可以使用许多技术来实现这一点。但是,方法上是扩展UniformGrid。
这种情况下的解决方案是覆盖MeasureOverride(),根据行中所有子项的最小高度或MinRowHeight计算新的大小,以较大者为准。
用法:
<UserControl x:Class="SOF.UniformGridMinHeight"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:sof="clr-namespace:SOF"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<sof:UniformGridEx Columns="3" MinRowHeight="100">
<Border Background="Red"/>
<Border Background="Blue"/>
<Border Background="Green"/>
<Border Background="Yellow"/>
<Border Background="Pink"/>
<Border Background="Purple"/>
<Border Background="LightCoral"/>
<Border Background="DimGray"/>
<Border Background="OrangeRed"/>
<Border Background="Olive"/>
<Border Background="Salmon"/>
</sof:UniformGridEx>
扩展UniformGrid:
public class UniformGridEx : UniformGrid
{
public static readonly DependencyProperty MinRowHeightProperty = DependencyProperty.Register(
"MinRowHeight", typeof(double), typeof(UniformGrid), new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure));
private int _columns;
private int _rows;
public double MinRowHeight
{
get { return (double)GetValue(MinRowHeightProperty); }
set { SetValue(MinRowHeightProperty, value); }
}
protected override Size MeasureOverride(Size constraint)
{
UpdateComputedValues();
var calculatedSize = base.MeasureOverride(constraint);
if (MinRowHeight > 0)
{
calculatedSize = new Size(calculatedSize.Width, Math.Max(calculatedSize.Height, _rows * MinRowHeight));
}
return calculatedSize;
}
private void UpdateComputedValues()
{
_columns = Columns;
_rows = Rows;
if (FirstColumn >= _columns)
{
FirstColumn = 0;
}
if ((_rows == 0) || (_columns == 0))
{
int nonCollapsedCount = 0;
for (int i = 0, count = InternalChildren.Count; i < count; ++i)
{
UIElement child = InternalChildren[i];
if (child.Visibility != Visibility.Collapsed)
{
nonCollapsedCount++;
}
}
if (nonCollapsedCount == 0)
{
nonCollapsedCount = 1;
}
if (_rows == 0)
{
if (_columns > 0)
{
_rows = (nonCollapsedCount + FirstColumn + (_columns - 1)) / _columns;
}
else
{
_rows = (int)Math.Sqrt(nonCollapsedCount);
if ((_rows * _rows) < nonCollapsedCount)
{
_rows++;
}
_columns = _rows;
}
}
else if (_columns == 0)
{
_columns = (nonCollapsedCount + (_rows - 1)) / _rows;
}
}
}
}发布于 2015-06-02 21:16:00
UniformGrid执行一个非常精确的任务...为所有项目提供完全相同大小的空间来呈现它们自己。如果您不需要该功能,那么您使用的Panel是错误的。尝试使用WrapPanel Class,它可以更好地处理不同大小的子项:
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>发布于 2015-09-23 18:23:54
我发现不久前我已经用下面的代码解决了这个问题。我的应用程序中有一个派生类,因此我可以覆盖ItemsControl的MeasureOverride方法。
class MyItemsControl : ItemsControl
{
// ...
protected override Size MeasureOverride(Size constraint)
{
Size size = base.MeasureOverride(constraint);
// Keep minimum height per item
int minHeight = Items.Count * 250;
if (size.Height < minHeight)
{
size.Height = minHeight;
}
return size;
}
}我的类的XAML代码如下所示:
<ItemsControl x:Class="MyItemsControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!-- Arrange all items vertically, distribute the space evenly -->
<UniformGrid Columns="1"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- Templates and other stuff ... -->
</ItemsControl>https://stackoverflow.com/questions/30596993
复制相似问题