2013-12-01 3 views
0

Я пытаюсь добавить поведение в свой ItemPanelTemplate, где все элементы свернуты, кроме одного сверху, поэтому я указал StackPanel с настраиваемым приложением.Добавление прикрепленного поведения к ItemsPanelTemplate

<ItemsControl ItemsSource="{Binding ViewModels}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <StackPanel my:ElementUtilities.CollapseAllButLast="True"/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 

Проблема заключается в том, что, когда обработчик события LayoutUpdated вызывается в моем поведении отправитель всегда нуль. Почему это?

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; 
    } 
} 

ответ

2

Согласно MSDN документации LayoutUpdated события -

При обращении LayoutUpdated, не полагаться на значение отправителя. Для LayoutОбновлен, отправитель всегда имеет значение, независимо от того, где установлен обработчик . Это делается для того, чтобы запретить обработчикам присвоить какой-либо смысл отправителю , например, подразумевая, что именно этот элемент поднял событие из визуального дерева.

Вместо этого вы можете подключить к loaded event -

if (e.NewValue != null && (bool)e.NewValue) 
    sp.Loaded += sp_Loaded; 
else 
    sp.Loaded -= sp_Loaded; 
Смежные вопросы