ListBoxItem.Parent returns nothing, unable to get it thru VisualTreeHelper.GetParent either

Shimmy Weitzhandler picture Shimmy Weitzhandler · Apr 13, 2010 · Viewed 7.4k times · Source

How do I extract the parent container of a ListBoxItem? In the following example I can go till the ListBoxItem, higher than that I get Nothing:

<ListBox Name="lbAddress">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <Button Click="Button_Click"/>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

Private Sub Button_Click(sender As Button, e As RoutedEventArgs)
  Dim lbAddress = GetAncestor(Of ListBox) 'Result: Nothing
End Sub

Public Shared Function GetAncestor(Of T)(reference As DependencyObject) As T
  Dim parent = GetParent(reference)

  While parent IsNot Nothing AndAlso Not parent.GetType.Equals(GetType(T))
    parent = GetAncestor(Of T)(parent)
  End While

  If parent IsNot Nothing Then _
    Return If(parent.GetType Is GetType(T), parent, Nothing) 

  Return Nothing    
End Sub

Public Function GetParent(reference As DependencyObject) As DependencyObject
  Dim parent As DependencyObject = Nothing

 If TypeOf reference Is FrameworkElement Then
    parent = DirectCast(reference, FrameworkElement).Parent
  ElseIf TypeOf reference Is FrameworkContentElement Then
    parent = DirectCast(reference, FrameworkContentElement).Parent
  End If

  Return If(parent, VisualTreeHelper.GetParent(reference))
End Function

Update

This is what happens (note that the 'parent' variable remains null):

This is how it looks like

Answer

Ray Burns picture Ray Burns · Apr 15, 2010

It is totally obvious something is removing an item from lbAddress.ItemsSource during the button click. The question is, what? A closer look at the image you posted reveals the answer. Here's the bug in your code:

My.Context.DeleteObject(context)
My.Context.SaveChanges()

   ...

btn.GetVisualAncestor(...)

The first two lines update your data model. This immediately removes the ListBoxItem from the visual tree. When when you call GetVisualAncestor later to find the ListBox it fails because the ListBoxItem no longer has a parent of any kind.

I'm sure the solution is now obvious to you: Simply find the ListBox ancestor before you delete the data from the data model and you'll be good to go.