当StackPanel父级调整大小时,改变StackPanel的子级
本文关键字:StackPanel 改变 调整 小时 | 更新日期: 2023-09-27 18:19:09
我在一个网格中有一些StackPanel
。它们被标签填充(所有标签的高度>可显示空间)。一个可能的XAML是:
<Grid>
<StackPanel>
<Label Content="bla" Background="lime" />
<Label ...>
...
</StackPanel>
</Grid>
每次Grid
的大小发生变化,我都需要改变StackPanel
的内部内容。我需要隐藏溢出的Label
,只显示部分。为了实现这一点,我可以使用以下解决方案:与转换器和创建一个继承自StackPanel的新类。
我想通过使用附加属性创建一种不同的方式。我有以下代码:
//DepProp OverflowVisibility (double), can save height value
public static void Initialized(DependencyObject pObject, DependencyPropertyChangedEventArgs e)
{
var panel = (pObject as Panel) //the StackPanel in this case
panel.SizeChanged += panel_updateInnerLayout;
}
static void panel_LayoutUpdated(object sender, EventArgs e)
{
var parent = sender as Panel;
if(parent != null)
foreach(FrameworkElement element in parent.Children)
{
var elementPos = element.TransformToAncestor(parent).Transform(new Point(0,0));
if(element.ActualHeight + elementPos.Y >
(double)parent.GetValue(OverflowVisibilityProperty))
element.Visibility = Visibility.Hidden;
else
element.Visibility = Visibility.Visible;
}
}
和在XAML中使用的示例:
<Grid>
<ItemsControl>
<ItemsPanel>
<ItemsPanelTemplate>
<StackPanel own:OverflowVisibility.OverflowVisibility="{Binding Grid height}" />
</ItemsPanelTemplate>
</ItemsPanel>
</ItemsControl>
</Grid>
每次StackPanel
改变它的大小,我可以用panel_updateInnerLayout
事件处理程序更新我的标签。当更改StackPanel
的大小时,一切都工作正常。
我的问题:StackPanel
本身不会提高SizeChanged
,因为它的高度比Grid
大。我需要一个事件,每次Grid
改变其高度时都会引发。
我的问题:是否有任何事件代替SizeChanged
,那是每次我改变Grid
大小调用?如果没有,是否有附加属性的替代方法来解决我的问题?
我也试图设置StackPanel
的高度绑定到ItemsControl
的ActualHeight,但它没有提高SizeChanged
。
不幸的是,您选择了错误的Panel
控件来满足您的需求。StackPanel
应该只在不需要调整其内容大小时使用,因为它不提供任何子控件调整大小的功能。因此,您应该使用Grid
,或任何其他提供调整大小功能的Panel
。
Panel
的进一步帮助。有两个可能的事件:SizeChanged
和LayoutUpdated
。SizeChanged
不工作,因为StackPanel没有调整大小。LayoutUpdated
不工作,因为这个事件的sender
总是null
,我无法找到StackPanel是什么来源。
更多信息请参见:Layout Events - SizeChanged and layoutupupdated。
所以我的方法没有可能的事件可用。
当我寻找解决方案时,我还发现,我使用了术语附加属性也用于附加行为和混合行为。这里描述了它们的区别。总结:属性对对象没有任何作用,但它们的存在可以被使用,行为改变对象的行为。Blend行为是微软为Microsoft Blend创建的行为。我的问题中的代码是附加行为。
对于附加行为我没有找到解决方案,但对于混合行为我找到了一些。您需要添加一个引用Micosoft.Windows.Interactivity
。
之后我使用了下面的代码:
public class OverflowVisibilityBehavior : Behavior<VirtualizingStackPanel>
{
protected override void OnAttached()
{
AssociatedObject.LayoutUpdated += AssociatedObject_LayoutUpdated;
base.OnAttached();
}
protected override void OnDetaching()
{
AssociatedObject.LayoutUpdated -= AssociatedObject_LayoutUpdated;
}
void AssociatedObject_LayoutUpdated(object sender, EventArgs e)
{
var parent = AssociatedObject; //that solves the problem: you can get a "sender" information
//...
// Instead of property GetValue
(VisualTreeHelper.GetParent(parent) as ItemsPresenter).ActualHeight
}
}
仍然存在一些问题:StackPanel的父级必须引发SizeChanged
。如果你把StackPanel
放到StackPanel
放到Grid
,你需要修改它。
第二:LayoutUpdated
多次修改StackPanel
。比我需要的还要多。