ListBoxItem.Parent 什么也不返回,也无法通过 VisualTreeHelper.GetParent 获取它
如何提取 ListBoxItem 的父容器? 在下面的示例中,我可以转到 ListBoxItem,高于此值时我什么也得不到:
<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
更新
这就是发生的情况(请注意,“父”变量保持为空):
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):
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
很明显,在单击按钮期间,某些东西正在从 lbAddress.ItemsSource 中删除项目。问题是,什么?仔细看看您发布的图片就会找到答案。这是代码中的错误:
前两行更新您的数据模型。这会立即从可视化树中删除 ListBoxItem。当您稍后调用 GetVisualAncestor 查找 ListBox 时,它会失败,因为 ListBoxItem 不再具有任何类型的父项。
我相信解决方案现在对您来说是显而易见的:只需在从数据模型中删除数据之前找到 ListBox 祖先,然后就可以开始了。
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: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.
罪魁祸首似乎是您的 GetParent 函数,它使用 Parent 属性而不是 VisualTreeHelper.GetParent。 Parent 属性返回逻辑父级,而不是可视父级,因此在尝试遍历 DataTemplate 时将返回 null。 (也不清楚 GetVisualAncestor 是如何实现的——或者这是 GetAncestor 的拼写错误?)一致地使用 VisualTreeHelper.GetParent,并忘记 Parent 属性。例如,以下代码适用于我:
XAML:
代码隐藏:
当我运行此代码时,Click 处理程序中的 ListBox 变量 (
lb
) 将设置为正确的非空值。The culprit appears to be your GetParent function, which uses the Parent property instead of VisualTreeHelper.GetParent. The Parent property returns the logical parent, not the visual parent, and will therefore return null when trying to traverse out of a DataTemplate. (It's also not clear how GetVisualAncestor is implemented -- or is this a typo for GetAncestor?) Use VisualTreeHelper.GetParent consistently, and forget about the Parent property. For example, the following code works for me:
XAML:
Code behind:
When I run this, the ListBox variable (
lb
) in the Click handler is set to the correct non-null value.Parent
属性返回逻辑父级。您应该使用视觉父级,因为在某些情况下逻辑父级将为空。例如,在您的情况下,按钮的Parent
属性返回 null。来自 MSDN :
由于
FrameworkElement.VisualParent
属性受到保护,因此您可以使用VisualTreeHelper.GetParent
方法:The
Parent
property returns the logical parent. You should use the visual parent, because in some cases the logical parent will be null. For instance, in your case theParent
property of the button returns null.From MSDN :
Since the
FrameworkElement.VisualParent
property is protected, you can use theVisualTreeHelper.GetParent
method :对于公认的纯 XAML 解决方案,您可以使用样式设置器将父
ListBox
填充到ListBoxItem 的
Tag
属性中(如果您没有将其用于任何其他目的):As for an admittedly-hacky XAML-only solution, you can use a Style setter to stuff the parent
ListBox
into theListBoxItem's
Tag
property (if you're not using it for any other purpose):