我正在尝试向我的ItemsPanelTemplate添加行为,其中所有项目都已折叠,但顶部的项目除外,因此我指定了一个具有自定义附加行为的StackPanel。
<ItemsControl ItemsSource="{Binding ViewModels}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel my:ElementUtilities.CollapseAllButLast="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
问题是当在我的行为中调用LayoutUpdated事件处理程序时,发送方始终为null。这是为什么?
public static class ElementUtilities
{
public static readonly DependencyProperty CollapseAllButLastProperty = DependencyProperty.RegisterAttached
("CollapseAllButLast", typeof(bool), typeof(ElementUtilities), new PropertyMetadata(false, CollapseAllButLastChanged));
static void CollapseAllButLastChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
StackPanel sp = o as StackPanel;
if (sp != null)
{
if (e.NewValue != null && (bool)e.NewValue)
sp.LayoutUpdated += sp_LayoutUpdated;
else
sp.LayoutUpdated -= sp_LayoutUpdated;
}
else
throw new InvalidOperationException("The attached CollapseAllButLast property can only be applied to StackPanel instances.");
}
public static bool GetCollapseAllButLast(StackPanel stackPanel)
{
if (stackPanel == null)
throw new ArgumentNullException("stackPanel");
return (bool)stackPanel.GetValue(CollapseAllButLastProperty);
}
public static void SetCollapseAllButLast(StackPanel stackPanel, bool collapseAllButLast)
{
if (stackPanel == null)
throw new ArgumentNullException("stackPanel");
stackPanel.SetValue(CollapseAllButLastProperty, collapseAllButLast);
}
static void sp_LayoutUpdated(object sender, EventArgs e)
{
// Collapse all but last element
StackPanel sp = (StackPanel)sender; // This is always null
for (int i = 0; i < sp.Children.Count - 1; i++)
{
UIElement l = sp.Children[i];
l.Visibility = Visibility.Collapsed;
}
sp.Children[sp.Children.Count - 1].Visibility = Visibility.Visible;
}
}
答案 0 :(得分:2)
根据LayoutUpdated事件的MSDN文档 -
处理LayoutUpdated时,请不要依赖发件人值。 :用于 LayoutUpdated,sender始终为null ,无论处理程序在何处 被附上。这是为了防止处理程序分配任何含义 发件人,例如暗示它是引发的特定元素 事件出自视觉树。
相反,您可以挂钩loaded event
-
if (e.NewValue != null && (bool)e.NewValue)
sp.Loaded += sp_Loaded;
else
sp.Loaded -= sp_Loaded;