如何使不适合其 parent 边界的控件消失
How to make a control disappear that doesn't fit into the bounds of its parent
我想创建一个控件(Panel
?),它可以容纳多个 child 控件并排列它们。但是我的控件应该只显示完全适合 parent 控件水平边界的 child 控件。所有其他 child 控件根本不应显示(无滚动条)。当我的控件的大小增加时,更多的 child 控件应该在适合增加的边界后立即变得可见。当然,如果我的控件变小,它们应该会再次消失。
现在我使用一个 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
这似乎符合我的要求。但是一旦只剩下一个 child 并且尺寸变得太小甚至无法显示这个 child,它就不会消失。原因是在MeasureOverride
中用availableSize
(太小的)来衡量child,所以这个child的DesiredSize
适合(太小)availableSize
.
然后我尝试使用水平StackPanel
并仅覆盖ArrangeOverride
,让StackPanel
进行排列,然后再决定是否删除child (Visibility
= 折叠)或不。但是我找不到一种方法来确定 child 是否适合其 parent 的范围,因为我找不到有关 "position" 的信息 child 在它的 parent 里面。有一个 VisualOffset
属性 看起来很有希望,但我无法访问它。
我考虑过覆盖 OnRenderSizeChanged
而不是 ArrangeOverride
,但我会遇到同样的问题,如何确定 child 是否适合其 [=54] 的范围=].
你能告诉我如何做我喜欢做的事情吗?
经过大量搜索后,我决定使用水平 StackPanel
并覆盖 ArrangeOverride
。我通过反射访问不可访问的 VisualOffset
属性(我知道,它不受欢迎)来检测排列的 child 的位置并决定它是否仍然可见。
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
我想创建一个控件(Panel
?),它可以容纳多个 child 控件并排列它们。但是我的控件应该只显示完全适合 parent 控件水平边界的 child 控件。所有其他 child 控件根本不应显示(无滚动条)。当我的控件的大小增加时,更多的 child 控件应该在适合增加的边界后立即变得可见。当然,如果我的控件变小,它们应该会再次消失。
现在我使用一个 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
这似乎符合我的要求。但是一旦只剩下一个 child 并且尺寸变得太小甚至无法显示这个 child,它就不会消失。原因是在MeasureOverride
中用availableSize
(太小的)来衡量child,所以这个child的DesiredSize
适合(太小)availableSize
.
然后我尝试使用水平StackPanel
并仅覆盖ArrangeOverride
,让StackPanel
进行排列,然后再决定是否删除child (Visibility
= 折叠)或不。但是我找不到一种方法来确定 child 是否适合其 parent 的范围,因为我找不到有关 "position" 的信息 child 在它的 parent 里面。有一个 VisualOffset
属性 看起来很有希望,但我无法访问它。
我考虑过覆盖 OnRenderSizeChanged
而不是 ArrangeOverride
,但我会遇到同样的问题,如何确定 child 是否适合其 [=54] 的范围=].
你能告诉我如何做我喜欢做的事情吗?
经过大量搜索后,我决定使用水平 StackPanel
并覆盖 ArrangeOverride
。我通过反射访问不可访问的 VisualOffset
属性(我知道,它不受欢迎)来检测排列的 child 的位置并决定它是否仍然可见。
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