【发布时间】:2014-11-17 14:40:56
【问题描述】:
我正在制作自己的自定义面板,当内容不适合可用空间时,它应该垂直滚动,所以我将它放在 ScrollViewer 中。 现在,当里面的面板比 ScrollViewer 本身大时,我无法让 ScrollViewer 激活滚动条。
permille 函数获得附加属性,告诉孩子必须与可用大小(不滚动)相比有多大,也就是 ViewPort。 由于在 MeasureOverride 中传递的大小是无限的,我认为我不能在那里使用 permille 函数。 这就是为什么我在 ArrangeOverride 中测量我的孩子(我猜这不是最佳实践)但这样滚动查看器不会滚动。
我如何让它工作?
我的 XAML 代码:
<ScrollViewer>
<controls:TilePanel x:Name="TilePanel" PreviewMouseLeftButtonDown="TilePanel_PreviewMouseLeftButtonDown" PreviewMouseLeftButtonUp="TilePanel_PreviewMouseLeftButtonUp"
PreviewMouseMove="TilePanel_PreviewMouseMove" DragEnter="TilePanel_DragEnter" Drop="TilePanel_Drop" AllowDrop="True" />
</ScrollViewer>
我的自定义面板类:
/// <summary>
/// A Panel Showing Tiles
/// </summary>
public class TilePanel : PermillePanel
{
public TilePanel()
{
}
protected override Size MeasureOverride(Size constraint)
{
//here constraint width or height can be infinite.
//as tiles are a permille of that height, they too can be infinite after measuring
//this is unwanted behavior, so we measure in the ArrangeOverride method
if (constraint.Width == double.PositiveInfinity)
{
return new Size(0, constraint.Height);
}
else if (constraint.Height == double.PositiveInfinity)
{
return new Size(constraint.Width, 0);
}
else
{
return constraint;
}
}
protected override Size ArrangeOverride(Size arrangeSize)
{
//return base.ArrangeOverride(arrangeSize);
foreach (FrameworkElement child in InternalChildren)
{
Size availableSize = new Size();
//set the width and height for the child
availableSize.Width = arrangeSize.Width * TilePanel.GetHorizontalPermille(child) / 1000;
availableSize.Height = arrangeSize.Height * TilePanel.GetVerticalPermille(child) / 1000;
child.Measure(availableSize);
}
// arrange the children on the panel
// fill lines horizontally, when we reach the end of the current line, continue to the next line
Size newSize = new Size(arrangeSize.Width, arrangeSize.Height);
double xlocation = 0;
double ylocation = 0;
double ystep = 0;
double maxYvalue = 0;
foreach (FrameworkElement child in InternalChildren)
{
double endxlocation = xlocation + child.DesiredSize.Width;
double constrainedWidth = arrangeSize.Width * TilePanel.GetHorizontalPermille(child) / 1000;
double constrainedHeight = arrangeSize.Height * TilePanel.GetVerticalPermille(child) / 1000;
if (TilePanel.GetVerticalPermille(child) != 0 && TilePanel.GetHorizontalPermille(child) != 0)
{
//horizontal overflow -> next line
if (endxlocation >= this.DesiredSize.Width *1.01)
{
ylocation += ystep;
xlocation = 0;
}
}
Rect rect = new Rect(xlocation, ylocation, constrainedWidth, constrainedHeight);
child.Arrange(rect);
xlocation += constrainedWidth;
ystep = Math.Max(ystep, constrainedHeight);
maxYvalue = Math.Max(maxYvalue, ystep + constrainedHeight);
}
if (maxYvalue > newSize.Height)
{
newSize.Height = maxYvalue;
}
return newSize;
}
}
【问题讨论】:
标签: c# wpf scrollviewer