【问题标题】:How to make a control disappear that doesn't fit into the bounds of its parent如何使不适合其父级范围的控件消失
【发布时间】:2019-10-30 05:00:08
【问题描述】:

我想创建一个控件 (Panel?),它可以容纳多个子控件并对其进行排列。但是我的控件应该只显示水平完全适合我的父控件边界的子控件。根本不应显示所有其他子控件(无滚动条)。当我的控件的大小增加时,更多的子控件应该在它们适合增加的范围后立即变得可见。当然,如果我的控件大小减小,它们应该会再次消失。

现在我使用带有自定义面板的ItemsControl 作为它的ItemPanel,这个自定义面板是我的控件。

首先我尝试从头开始创建一个自定义面板(继承自 Panel),但我无法自始至终完成测量和安排工作。

Protected Overrides Function MeasureOverride(availableSize As Size) As Size
    Dim result As Size

    For Each child As UIElement In Me.InternalChildren
        child.Measure(availableSize)

        result.Width += child.DesiredSize.Width
        result.Height = Math.Max(result.Height, child.DesiredSize.Height)
    Next child

    Return New Size(Math.Min(result.Width, availableSize.Width), Math.Min(result.Height, availableSize.Height))
End Function

Protected Overrides Function ArrangeOverride(finalSize As Size) As Size
    Dim left As Double
    Dim bounds As Rect

    left = 0.0

    For Each child As UIElement In Me.InternalChildren
        If ((left + child.DesiredSize.Width) > finalSize.Width) Then
            child.Arrange(New Rect)
        Else
            bounds = New Rect
            bounds.X = left
            bounds.Y = 0
            bounds.Width = child.DesiredSize.Width
            bounds.Height = child.DesiredSize.Height

            child.Arrange(bounds)
        End If

        left += child.DesiredSize.Width
    Next child

    Return finalSize
End Function

这似乎按我想要的方式工作。但是一旦只剩下一个孩子并且尺寸变得太小甚至无法显示这个孩子,它就不会消失。原因是MeasureOverride中的availableSize(太小)是用来衡量孩子的,所以这个孩子的DesiredSize适合(太小)availableSize

然后我尝试使用水平的StackPanel 并仅覆盖ArrangeOverride,让StackPanel 进行安排并在之后决定是否删除一个孩子(Visibility = Collapsed)。但是我无法找到一种方法来确定孩子是否适合其父母的界限,因为我无法找到有关孩子在其父母中的“位置”的信息。有一个 VisualOffset 属性看起来很有希望,但我无法访问它。

我考虑过覆盖 OnRenderSizeChanged 而不是 ArrangeOverride,但我会遇到同样的问题,即如何确定孩子是否适合其父母的界限。

你能告诉我如何做我喜欢做的事吗?

【问题讨论】:

    标签: wpf vb.net panel


    【解决方案1】:

    经过大量搜索后,我决定使用水平的StackPanel 并覆盖ArrangeOverride。我通过反射访问不可访问的VisualOffset 属性(我知道,它不赞成)以检测已安排子项的位置并确定它是否仍然可见。

    Protected Overrides Function ArrangeOverride(arrangeSize As Size) As Size
        Dim result As Size
        Dim visualOffset As Vector
    
        result = MyBase.ArrangeOverride(arrangeSize)
    
        For Each element As UIElement In MyBase.InternalChildren
            visualOffset = element.GetType.GetProperty("VisualOffset", BindingFlags.NonPublic Or BindingFlags.Instance).GetValue(element)
    
            If visualOffset.X + element.DesiredSize.Width > MyBase.DesiredSize.Width Then
                element.Arrange(New Rect)   'hide the element without breaking possible Visibility bindings
            End If
        Next element
    
        Return result
    End Function
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-08
      • 1970-01-01
      • 2011-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-11
      相关资源
      最近更新 更多