【问题标题】:Why does the Parent property of a container of an ItemsControl return null and not the Panel it sits on?为什么 ItemsControl 的容器的 Parent 属性返回 null 而不是它所在的 Panel?
【发布时间】:2013-01-02 07:35:52
【问题描述】:

这个让我难过。我们有一个自定义 ItemsControl,它使用自定义容器和自定义面板作为其 ItemsHost。现在,面板具有容器渲染所需的一些指标。由于它们是可视树中面板的直接子级,您可能会认为容器的 Parent 属性会返回面板,但事实并非如此!

我还在标准 ListBox 上使用 Snoop 确认了这一点,所以这不是我们的代码所独有的,显然是 ItemsControls 的所有容器。

现在我知道我可以使用 VisualTreeHelper 来获取可视父级(这是我需要的),但是为什么父级不是是面板?

如果参数是面板只是可视树的一部分,而父级是为逻辑树保留的,那么父级不是 ItemsControl 吗?

如果容器的参数也是 ItemsControl 的可视化树的一部分,而不是逻辑树的一部分,那么为什么容器中托管的内容会将容器作为其 Parent 属性返回?

这意味着,如果您从数据项遍历逻辑树,您会在容器处停下来,这可以解释为什么我们从容器到面板的绑定没有按预期工作。 (我相信绑定是基于逻辑层次结构而不是视觉层次结构,但我必须进行测试才能确定。)

【问题讨论】:

  • 问得好,我也一直想知道。附注:您也可以使用ItemsControl.GetItemsOwner 获取ItemsControl
  • 是的,但如果不明确编写转换器,您将无法在绑定中执行此操作。使用 RelativeSource 搜索树似乎失败了;我的猜测是出于我指出的确切原因......容器的父级是 Null。
  • 这确实是一个好问题。我相信会读到一些 listboxitem 有一个非公共成员来获取父级的地方。但是,如果您使用自定义容器,那么您将负责在创建时设置父容器。

标签: wpf parent itemscontrol visualtreehelper


【解决方案1】:

我从未注意到这一点,这激起了我的好奇心。 在 .Net Framework 中寻找线索后,发现 Parent 属性似乎确实是手动设置的: 这需要几个步骤,但我发现更改父属性的唯一方法是调用这些方法:

如果我分析例如 FrameworkElement.AddLogicalChild 方法,我发现这些方法正在使用它:

这确认了父属性应该引用逻辑树。 我尝试创建自己的自定义控件:

[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>

...这就像这样(就像一个魅力:-)):

...猜猜看... 矩形的父级未设置:-)

我现在没有时间继续调查,但是关于 ItemsControl,我想可能 ItemContainerGenerator 不知道它在其中插入 itemsContainers 的逻辑父级,这可以解释为什么在这种情况下没有设置 parent 属性。 ..但这需要证明...

【讨论】:

  • 很棒的研究! (......对不起,我没有早点看到这个。)还有很多细节!更多的SO答案应该是这样的。给你答案投票,因为这应该足以回答最初的问题,并为那些想要更深入的人指明方向。
  • 您的图片似乎丢失了。有机会直接上传吗?没有他们,答案就不像以前那么清楚了。
  • 感谢您的关注。但是??..据我所见,图像仍然显示
  • 我的错。工作中的代理问题,由于某种原因,它们阻止了托管在 SO 上的图像。它们实际上仍然存在,并且已经存在两年了。
【解决方案2】:

FrameworkElement.Parent 属性 documentation 表示它可能为空,例如对于在数据模板中创建的项目。在这种情况下,他们建议使用FrameworkElement.TemplatedParent

对于模板,模板的 Parent 最终将为 null。到 越过这一点并扩展到逻辑树中 实际应用模板,使用 TemplatedParent。

可能是你的情况?它在类似的情况下帮助了我(我使用了Parent,然后如果它为空,则使用TemplateParent 作为后备)。

是的,答案来晚了,但它可能会帮助其他遇到与我相同错误的人

【讨论】:

  • 如果这是真的,那么您为我节省了大量工作! Null-coalescing 运算符来救援!
猜你喜欢
  • 2021-12-07
  • 1970-01-01
  • 2021-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
相关资源
最近更新 更多