如何创建一个Silverlight面板来安排子项以防止重叠?

时间:2009-03-13 17:27:12

标签: silverlight-2.0

我正在尝试创建一个使用绝对定位的自定义面板,但会重新排列项目,以便所有子项都不会重叠。此面板将用于ItemsControl的ItemsPanel。 ItemsControl绑定到在各个城市的地图上显示为插入的数据,因此目标是使插图保持接近其城市而不重叠任何其他插入。我有一个重新排列项目的算法(虽然它很慢,我有兴趣找到一个更好的,所以如果有人有建议,请告诉我),但我一直在努力与自定义面板。

最新的代码可以在下面找到减去算法以缩短它。我还附上了一个图像,显示了视觉树在重叠区域下的样子。

问题:

1。)我遇到的第一个问题是,尽管MSDN说如果想要占用可用的全部空间,MeasureOverride应该返回正无穷大的高度和宽度,当我尝试这样做时会出现错误。因此,我遇到了一些问题,其中我的一些子项被剪切,因为包含OverlapPanel的ItemsPresenter仅调整返回的MeasureOverride大小并剪切我的一些插图,因为在ArrangeOverride之后,它们被移动并且最终尺寸更大。

2.。)我尝试使用VisualTreeHelper.FindElementInHostCoordinates,使用每个“ItemsControl”的Canvas.Left和Canvas.Top属性,在每个插图的“ContentPresenter”下面的几个级别找到OverlapPanel子树中的其他重叠项。我必须深入到ItemsControl的原因是因为它是第一个具有有效canvas.top和left属性以及DesiredSize.Width和DesiredSize.Height的项目。但是,无论我试图尝试什么,FindElementInHostCoordinates都会返回0项。我甚至尝试使用TransformToVisual将我的坐标转换为各种级别,然后再使用它,我仍然无法得到任何预期的结果。

3。)由于我使用OverlapPanel作为ItemsControl的ItemsPanel,我必须向下钻取几个级别的可视树以获得实际的左/顶值和宽度/高度来计算定位但这不会不允许面板用作通用面板。我怎么能让它在整体上变得更有用呢?

这是我目前正在使用的代码。请注意,“PreArrange”最终会在每个子元素上调用“Arrange”,并设置其左/顶属性。为了简洁,我把代码留给了它。:

Protected Overrides Function MeasureOverride(ByVal availableSize As System.Windows.Size) As System.Windows.Size
        'Return MyBase.MeasureOverride(availableSize)
        Dim infinite As New Size(Double.PositiveInfinity, Double.PositiveInfinity)

        Dim maxX, maxY As Double
        maxX = 0
        maxY = 0

        For Each elem As FrameworkElement In Children
            elem.Measure(infinite)
            Dim ic As ItemsControl = CType(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(elem, 0), 0), ItemsControl)
            If (elem.GetValue(Canvas.LeftProperty) + ic.DesiredSize.Width) > maxX Then
                maxX = elem.GetValue(Canvas.LeftProperty) + ic.DesiredSize.Width
            End If
            If (elem.GetValue(Canvas.TopProperty) + ic.DesiredSize.Height) > maxY Then
                maxY = elem.GetValue(Canvas.TopProperty) + ic.DesiredSize.Height
            End If
        Next

        Return New Size(maxX, maxY)
    End Function

    Protected Overrides Function ArrangeOverride(ByVal finalSize As System.Windows.Size) As System.Windows.Size
        If Children.Count = 0 Then
            Return MyBase.ArrangeOverride(finalSize) 'New Size(Width, Height)
        End If

        Dim maxX As Double = 0
        Dim minX As Double = 0
        Dim maxY As Double = 0
        Dim minY As Double = 0

        For i As Integer = 0 To Children.Count - 1
            PreArrange(Children(i), 5, 1, 10)
            Dim ic As ItemsControl = CType(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(Children(i), 0), 0), ItemsControl)
            Dim x1 As Double = Children(i).GetValue(Canvas.LeftProperty)
            Dim x2 As Double = ic.DesiredSize.Width + x1
            Dim y1 As Double = Children(i).GetValue(Canvas.TopProperty)
            Dim y2 As Double = ic.DesiredSize.Height + y1

            If x1 < minX Then minX = x1
            If x2 > maxX Then maxX = x2
            If y1 < minY Then minY = y1
            If y2 > maxY Then maxY = y2
        Next


        Return New Size(Math.Abs(minX) + maxX, Math.Abs(minY) + maxY)
        'Return MyBase.ArrangeOverride(finalSize)
    End Function

alt text http://www.mistertnt.com/images/OverlapPanelVisualTree.jpg

1 个答案:

答案 0 :(得分:0)