【问题标题】:How can I create a Silverlight Panel that arranges child items to prevent overlapping?如何创建一个 Silverlight 面板来排列子项以防止重叠?
【发布时间】:2009-03-13 17:27:12
【问题描述】:

我正在尝试创建一个自定义面板,该面板利用绝对定位但会重新排列项目,以使所有子项都不会重叠。此面板将用于 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

【问题讨论】:

    标签: silverlight-2.0


    【解决方案1】:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    • 2012-10-07
    • 1970-01-01
    相关资源
    最近更新 更多