I've created a ListBox to display items in groups, where the groups are wrapped right to left when they can no longer fit within the height of the ListBox's panel. So, the groups would appear similar to this in the listbox, where each group's height is arbitrary (group 1, for instance, is twice as tall as group 2):
我创建了一个ListBox来显示组中的项目,当它们不再适合ListBox面板的高度时,这些组从右到左包装。因此,组在列表框中看起来与此类似,其中每个组的高度是任意的(例如,组1是组2的两倍):
[ 1 ][ 3 ][ 5 ]
[ ][ 4 ][ 6 ]
[ 2 ][ ]
The following XAML works correctly in that it performs the wrapping, and allows the horizontal scroll bar to appear when the items run off the right side of the ListBox.
以下XAML正常工作,它执行包装,并允许水平滚动条在项目从ListBox的右侧运行时出现。
The problem occurs when a group of items is longer than the height of the WrapPanel. Instead of allowing the vertical scroll bar to appear to view the cutoff item group, the items in that group are simply clipped. I'm assuming that this is a side effect of the Height binding in the WrapPanel - the scrollbar thinks it does not have to enabled.
当一组项目长于WrapPanel的高度时,会发生此问题。不是允许垂直滚动条显示以查看截止项组,而是简单地剪切该组中的项目。我假设这是WrapPanel中高度绑定的副作用 - 滚动条认为它不必启用。
Is there any way to enable the scrollbar, or another way around this issue that I'm not seeing?
有没有办法启用滚动条,或者我没有看到这个问题的另一种方法?
2
By setting the Height property on the WrapPanel to the height of the ScrollContentPresenter, it will never scroll vertically. However, if you remove that Binding, it will never wrap, since in the layout pass, it has infinite height to layout in.
通过将WrapPanel上的Height属性设置为ScrollContentPresenter的高度,它将永远不会垂直滚动。但是,如果删除该Binding,它将永远不会换行,因为在布局过程中,它具有无限的布局高度。
I would suggest creating your own panel class to get the behavior you want. Have a separate dependency property that you can bind the desired height to, so you can use that to calculate the target height in the measure and arrange steps. If any one child is taller than the desired height, use that child's height as the target height to calculate the wrapping.
我建议您创建自己的面板类以获得所需的行为。有一个单独的依赖项属性,您可以将所需的高度绑定到,因此您可以使用它来计算度量中的目标高度并安排步骤。如果任何一个孩子的身高高于所需的身高,请使用该孩子的身高作为目标身高来计算包裹。
Here is an example panel to do this:
以下是执行此操作的示例面板:
public class SmartWrapPanel : WrapPanel
{
///
/// Identifies the DesiredHeight dependency property
///
public static readonly DependencyProperty DesiredHeightProperty = DependencyProperty.Register(
"DesiredHeight",
typeof(double),
typeof(SmartWrapPanel),
new FrameworkPropertyMetadata(Double.NaN,
FrameworkPropertyMetadataOptions.AffectsArrange |
FrameworkPropertyMetadataOptions.AffectsMeasure));
///
/// Gets or sets the height to attempt to be. If any child is taller than this, will use the child's height.
///
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));
}
}
2
Here is the slightly modified code - all credit given to Abe Heidebrecht, who previously posted it - that allows both horizontal and vertical scrolling. The only change is that the return value of MeasureOverride needs to be base.MeasureOverride(new Size(ret.width, h)).
这是稍微修改过的代码 - 所有信用都给予了之前发布的Abe Heidebrecht,允许水平和垂直滚动。唯一的变化是MeasureOverride的返回值需要是base.MeasureOverride(new Size(ret.width,h))。
// Original code : Abe Heidebrecht
public class SmartWrapPanel : WrapPanel
{
///
/// Identifies the DesiredHeight dependency property
///
public static readonly DependencyProperty DesiredHeightProperty = DependencyProperty.Register(
"DesiredHeight",
typeof(double),
typeof(SmartWrapPanel),
new FrameworkPropertyMetadata(Double.NaN,
FrameworkPropertyMetadataOptions.AffectsArrange |
FrameworkPropertyMetadataOptions.AffectsMeasure));
///
/// Gets or sets the height to attempt to be. If any child is taller than this, will use the child's height.
///
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));
}
}
0
Thanks for answering, David.
谢谢你回答,大卫。
When the binding is removed
, no wrapping occurs. The WrapPanel puts every group into a single vertical column.
删除绑定后,不会发生包装。 WrapPanel将每个组放入一个垂直列。
The binding is meant to force the WrapPanel to actually wrap. If no binding is set, the WrapPanel assumes the height is infinite and never wraps.
绑定意味着强制WrapPanel实际包装。如果未设置任何绑定,则WrapPanel假定高度为无限且永不包裹。
Binding to MinHeight
results in an empty listbox. I can see how the VerticalAlignment
property could seem to be a solution, but alignment itself prevents any wrapping from occurring. When binding and alignment are used together, the alignment has no effect on the problem.
绑定到MinHeight会导致空列表框。我可以看到VerticalAlignment属性似乎是一个解决方案,但对齐本身可以防止任何包装发生。当一起使用绑定和对齐时,对齐对问题没有影响。
0
I would think that you are correct that it has to do with the binding. What happens when you remove the binding? With the binding are you trying to fill up at least the entire height of the list box? If so, consider binding to MinHeight instead, or try using the VerticalAlignment
property.
我认为你是正确的,它与绑定有关。删除绑定后会发生什么?你试图填充至少列表框的整个高度?如果是这样,请考虑绑定到MinHeight,或尝试使用VerticalAlignment属性。