我已经创建了一个ListBox来显示组中的项目,当这些组不再适合ListBox的面板高度时,将这些组从右向左包裹。因此,组在列表框中的显示类似于此,其中每个组的高度是任意的(例如,组1的高度是组2的两倍):
1 2 3
| [ 1 ][ 3 ][ 5 ]
[ ][ 4 ][ 6 ]
[ 2 ][ ] |
以下XAML可以正常工作,因为它执行了package,并且当项目从ListBox的右侧运行时,允许水平滚动条出现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.GroupStyle>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical"
Height="{Binding Path=ActualHeight,
RelativeSource={RelativeSource
FindAncestor,
AncestorLevel=1,
AncestorType={x:Type ScrollContentPresenter}}}"/>
</ItemsPanelTemplate>
</ListBox.GroupStyle>
</ListBox> |
当一组项目的长度大于WrapPanel的高度时,会发生此问题。除了允许垂直滚动条显示以查看截止项目组之外,还可以仅剪切该组中的项目。我假设这是WrapPanel中Height绑定的副作用-滚动条认为不必启用它。
是否有任何启用滚动条的方法,或者解决了我没有看到的此问题的另一种方法?
这里是经过略微修改的代码-先前发布该代码的所有人员均归功于Abe Heidebrecht-该代码允许水平和垂直滚动。唯一的变化是MeasureOverride的返回值必须为base.MeasureOverride(new Size(ret.width,h))。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| // Original code : Abe Heidebrecht
public class SmartWrapPanel : WrapPanel
{
/// <summary>
/// Identifies the DesiredHeight dependency property
/// </summary>
public static readonly DependencyProperty DesiredHeightProperty = DependencyProperty.Register(
"DesiredHeight",
typeof(double),
typeof(SmartWrapPanel),
new FrameworkPropertyMetadata(Double.NaN,
FrameworkPropertyMetadataOptions.AffectsArrange |
FrameworkPropertyMetadataOptions.AffectsMeasure));
/// <summary>
/// Gets or sets the height to attempt to be. If any child is taller than this, will use the child's height.
/// </summary>
public double DesiredHeight
{
get { return (double)GetValue(DesiredHeightProperty); }
set { SetValue(DesiredHeightProperty, value); }
}
protected override Size MeasureOverride(Size constraint)
{
Size ret = base.MeasureOverride(constraint);
double h = ret.Height;
if (!Double.IsNaN(DesiredHeight))
{
h = DesiredHeight;
foreach (UIElement child in Children)
{
if (child.DesiredSize.Height > h)
h = child.DesiredSize.Height;
}
}
return base.MeasureOverride(new Size(ret.Width, h));
}
protected override System.Windows.Size ArrangeOverride(Size finalSize)
{
double h = finalSize.Height;
if (!Double.IsNaN(DesiredHeight))
{
h = DesiredHeight;
foreach (UIElement child in Children)
{
if (child.DesiredSize.Height > h)
h = child.DesiredSize.Height;
}
}
return base.ArrangeOverride(new Size(finalSize.Width, h));
}
} |
通过将WrapPanel上的Height属性设置为ScrollContentPresenter的高度,它将永远不会垂直滚动。但是,如果删除该Binding,它将永远不会换行,因为在布局传递中,它在布局中的高度是无限的。
我建议您创建自己的面板类以获取所需的行为。有一个单独的依赖项属性,可以将所需的高度绑定到该属性,因此可以使用该属性来计算度量中的目标高度并安排步骤。如果任何一个孩子的身高超过所需的身高,请使用该孩子的身高作为目标身高,以计算包裹率。
以下是执行此操作的示例面板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| public class SmartWrapPanel : WrapPanel
{
/// <summary>
/// Identifies the DesiredHeight dependency property
/// </summary>
public static readonly DependencyProperty DesiredHeightProperty = DependencyProperty.Register(
"DesiredHeight",
typeof(double),
typeof(SmartWrapPanel),
new FrameworkPropertyMetadata(Double.NaN,
FrameworkPropertyMetadataOptions.AffectsArrange |
FrameworkPropertyMetadataOptions.AffectsMeasure));
/// <summary>
/// Gets or sets the height to attempt to be. If any child is taller than this, will use the child's height.
/// </summary>
public double DesiredHeight
{
get { return (double)GetValue(DesiredHeightProperty); }
set { SetValue(DesiredHeightProperty, value); }
}
protected override Size MeasureOverride(Size constraint)
{
Size ret = base.MeasureOverride(constraint);
double h = ret.Height;
if (!Double.IsNaN(DesiredHeight))
{
h = DesiredHeight;
foreach (UIElement child in Children)
{
if (child.DesiredSize.Height > h)
h = child.DesiredSize.Height;
}
}
return new Size(ret.Width, h);
}
protected override System.Windows.Size ArrangeOverride(Size finalSize)
{
double h = finalSize.Height;
if (!Double.IsNaN(DesiredHeight))
{
h = DesiredHeight;
foreach (UIElement child in Children)
{
if (child.DesiredSize.Height > h)
h = child.DesiredSize.Height;
}
}
return base.ArrangeOverride(new Size(finalSize.Width, h));
}
} |
大卫,谢谢您的回答。
当绑定为removed时,不会发生换行。 WrapPanel将每个组放入单个垂直列中。
该绑定用于强制WrapPanel实际package。如果未设置任何绑定,则WrapPanel假定高度为无限且从不环绕。
绑定到MinHeight会导致一个空的列表框。我可以看到VerticalAlignment属性似乎是一个解决方案,但是对齐本身可以防止发生任何换行。当绑定和对齐方式一起使用时,对齐方式不会对问题产生影响。
我认为您与绑定有关是正确的。删除绑定后会发生什么?通过绑定,您是否要填充至少列表框的整个高度?如果是这样,请考虑绑定到MinHeight,或者尝试使用VerticalAlignment属性。