问题描述
这个让我难过.我们有一个自定义ItemsControl,它同时使用自定义容器和自定义面板作为ItemsHost.现在,该面板具有容器用于渲染目的所需的一些度量.由于它们是面板在视觉树中的直接子代,因此您认为容器的Parent属性将返回面板,但事实并非如此!
This one has me stumped. We have a custom ItemsControl which uses both custom containers as well as a custom panel as its ItemsHost. Now the panel has some metrics that the containers need for rendering purposes. Since they are direct children of the panel in the visual tree, you'd think that the Parent property of the container would return the panel, but it doesn't!
我也已经在标准ListBox上使用Snoop确认了这件事,所以这并不是我们的代码独有,但显然是ItemsControls的所有容器.
I have also confirmed this exact thing using Snoop on a standard ListBox so this isn't exclusive to our code, but apparently all containers of ItemsControls.
现在我知道我可以使用VisualTreeHelper来获取可视父对象(这是我所需要的),但是为什么父不是会成为面板?
Now I know I can use the VisualTreeHelper to get the visual parent (which is what I need) but why would the parent not be the panel?
如果参数是面板只是可视化树的一部分,而父级是为逻辑树保留的,那么父级不就是ItemsControl吗?
If the argument is that the panel is simply part of the Visual Tree and Parent is reserved for the Logical Tree, then wouldn't the parent be the ItemsControl?
如果参数中也有容器,那么它也是ItemsControl可视树的一部分,而不是逻辑树的一部分,那么为什么容器中托管的内容将容器作为其Parent属性返回?
If the argument there is the container too is part of the ItemsControl's visual tree and not the logical tree, then why would the contents hosted in the container return the container as its Parent property?
这意味着,如果您从数据项中走逻辑树,则在容器处停止,这可以解释为什么我们从容器到面板的绑定无法按预期工作. (我相信绑定是基于逻辑层次结构,而不是视觉层次结构,但是我必须进行测试才能确定.)
That means if you're walking the logical tree from a data item, you stop at the containers, which may explain why our bindings from the containers to the panels aren't working as expected. (I believe bindings are based on a logical hierarchy and not a visual one, but I'd have to test to be sure.)
推荐答案
我从没注意到这一点,这激起了我的好奇心.在.Net Framework中寻找线索后,发现Parent属性似乎确实是手动设置的:这需要几个步骤,但是我发现更改父属性的唯一方法是调用以下方法:
I never noticed that and this spiked my curiosity.After looking for clues in the .Net Framework in found that Parent property seems indeed to be set manualy:This required several steps but I found that the only way to change the parent property is to invoke these methods:
如果我分析例如FrameworkElement.AddLogicalChild方法,我发现这些方法正在使用它:
If I analyse for example the FrameworkElement.AddLogicalChild method, I found that these methods are using it:
这确认了父属性应该引用逻辑树.我试图创建自己的自定义控件:
This confirms that the parent property is supposed to refer to the logical tree.I tried to create my own custom control:
[ContentProperty("CustomContent")]
public class CustomControl1 : Control
{
static CustomControl1()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
}
public object CustomContent
{
get { return GetValue(CustomContentProperty); }
set { SetValue(CustomContentProperty, value); }
}
public static readonly DependencyProperty CustomContentProperty = DependencyProperty.Register("CustomContent", typeof(object), typeof(CustomControl1));
}
使用此模板:
<ControlTemplate TargetType="{x:Type local:CustomControl1}">
<ContentPresenter ContentSource="CustomContent" />
</ControlTemplate>
我是这样使用的:
<WpfApplication1:CustomControl1 Width="50" Height="50">
<Rectangle Fill="Red" />
</WpfApplication1:CustomControl1>
...这样工作(就像一个魅力:-)):
... this worked like this (like a charm :-)):
...,然后猜猜... 未设置矩形的父级:-)
... and guess what... Parent of the rectangle is not set :-)
我现在没有时间继续调查,但是关于ItemsControl,我想也许ItemContainerGenerator不知道在其中插入itemsContainers的逻辑父对象,这可以解释为什么在这种情况下未设置父属性. ..但这需要证明...
I don't have time to continue investigating for now but regarding ItemsControl, I imagine that maybe the ItemContainerGenerator doesn't know the logical parent in which it inserts itemsContainers, that could explain why parent property is not set in this case... but that need to be proven...
这篇关于为什么ItemsControl的容器的Parent属性返回null,而不返回它所在的Panel?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!