我知道我可以在这种情况下使用WrapPanel
但是有什么方法可以实现我正在寻找的东西。我想使用StackPanel
作为ListBox
的项目面板,其中方向设置为水平。我可以得到StackPanel
的子项超出父控件/容器宽度的情况。因此,例如,如果我有一个StackPanel
,其中5个文本块设置为水平方向,然后我将窗口拖动宽度使其变小,在某个时刻,第5 TextBox
将延伸到屏幕外(隐藏)。在这一点上,我想要某种数据触发器将方向设置为垂直,几乎就像一个响应式设计。有没有办法做到这一点?
答案 0 :(得分:1)
有办法做到这一点吗?
您可以处理SizeChanged
事件。以下代码示例应该为您提供想法。如果最后一个元素(Orientation
)被隐藏,它会将Horizontal
设置为TextBox
,并在宽度增加时将其设置回Vertical
。
private void ListBox_SizeChanged(object sender, SizeChangedEventArgs e)
{
ListBox lb = sender as ListBox;
ItemsPresenter ip = FindVisualChild<ItemsPresenter>(lb);
StackPanel sp = FindVisualChild<StackPanel>(ip);
UIElement lastElement = sp.Children[sp.Children.Count - 1];
bool isLastElementVisible = IsElementVisible(lastElement);
if (e.NewSize.Width < e.PreviousSize.Width && !isLastElementVisible)
sp.Orientation = Orientation.Vertical;
else if (e.NewSize.Width > e.PreviousSize.Width && isLastElementVisible)
sp.Orientation = Orientation.Horizontal;
}
private static T FindVisualChild<T>(DependencyObject parent, string childName = null) where T : DependencyObject
{
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
var childElement = child as FrameworkElement;
if (child is T && (childName == null || (childElement != null && childElement.Name == childName)))
{
return child as T;
}
else
{
var grandchild = FindVisualChild<T>(child, childName);
if (grandchild is T)
{
return grandchild;
}
}
}
return null;
}
private static bool IsElementVisible(UIElement element)
{
if (!element.IsVisible)
return false;
var container = VisualTreeHelper.GetParent(element) as FrameworkElement;
if (container == null) throw new ArgumentNullException("container");
Rect bounds = element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.RenderSize.Width, element.RenderSize.Height));
Rect rect = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);
return rect.IntersectsWith(bounds);
}
<强> XAML:强>
<ListBox SizeChanged="ListBox_SizeChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<TextBox Width="100" Text="1" />
<TextBox Width="100" Text="2" />
<TextBox Width="100" Text="3" />
<TextBox Width="100" Text="4" />
<TextBox Width="100" Text="5" />
</ListBox>