【问题标题】:Is there a way to determine where a WPF Binding is declared/created?有没有办法确定 WPF 绑定的声明/创建位置?
【发布时间】:2013-01-08 18:35:56
【问题描述】:

我有一个项目引发了一些数据绑定错误。一个例子是:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')

我的问题是是否有办法确定此绑定的实际声明位置(在 XAML 或代码中声明)。

到目前为止我已经尝试过:

  • 为 System.Windows.Data 命名空间添加了调试跟踪,级别设置为全部;这并没有产生任何更有用的信息
  • 尝试在项目中对单词Binding 进行文本搜索,希望能找到所有将Path 设置为HorizontalContentAlignment 的绑定表达式;我只找到了一个并将其删除,但我仍然收到消息,这似乎表明那不是有故障的..

您是否知道任何其他技巧可以让 WPF 吐出一些更有用的信息,说明此绑定的确切声明位置?

更新

经过更多搜索后,我很确定这是由于某种样式应用于MenuItem 造成的。但是,我仍然无法确定错误绑定被声明的位置..

更新 2

我发现了问题。但是问题仍然存在,因为发现问题主要是根据错误消息中的有限信息在黑暗中搜索的问题。

事实证明,绑定是在样式中声明的。而且样式不在我的应用程序中。这可能是MenuItem 的默认样式。所以现在要解决这个问题,我只是在所有MenuItems 上手动设置HorizontalContentAlignment。错误的原因在某种程度上与操作顺序有关,因为这个MenuItem 是在代码中生成的。我将单独发布一个新问题。

所以,就目前而言,这个故事的寓意是,我觉得需要一种更好的机制来确定错误绑定的声明位置。我希望看到类似绑定的堆栈跟踪。

如果有人知道任何其他工具或方法可以确定在代码或标记中声明绑定的位置,我将把这个问题保持一段时间。

我已经发布了另一个question regarding the style/binding being applied to the MenuItems here

【问题讨论】:

  • Hrrm 我最近写了一个关于绑定错误的答案here。错误告诉您它正在尝试绑定 <MenuItem HorizontalContentAlignment={ItemsControl.HorizontalContentAlignment}">,但 WPF 无法找到 ItemsControl“找不到绑定源”)。这可能是因为ContextMenus are not part of the same VisualTree as the rest of the application,所以你需要在你的绑定中使用PlacementTarget来访问ContextMenu所附加的对象。
  • 当异常发生时您是否尝试捕获异常?从 Debug 菜单中,选择 Exceptions... 并深入到您遇到的异常,然后选中“Thrown”框。不确定它是否会有所帮助,但还有一件事要尝试。
  • 但要回答您发布的实际问题,我喜欢使用Snoop 来调试 WPF 绑定错误。它将让您轻松浏览 VisualTree,并向您显示任何绑定问题
  • @Rachel - 感谢您提供的信息。我会看看你的帖子。我也会和 Snoop 一起尝试一下,看看我是否可以通过这种方式对此事有所了解。否则,问题是我在代码或 XAML 中没有绑定 Horizo​​ntalContentAlignment 的位置..奇怪..
  • 任何想法如何使用 Snoop 来确定 BindingErrors 可能发生的位置?我尝试了“仅显示具有绑定错误的视觉效果”,但什么也没找到..

标签: wpf data-binding


【解决方案1】:

也许您可以使用这个名为Snoop 的出色应用程序。在CodePlex 是免费的。它帮助我找到了几个绑定问题,以及丢失的数据上下文。它可以让您探索整个 WPF 可视化树,并为您提供绑定错误。

希望 Snoop 可以提供帮助。

【讨论】:

    【解决方案2】:

    在调试 WPF 绑定错误时,我发现用分号将错误分开,从头开始

    1. System.Windows.Data Error: 4 :
    2. Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment;
    3. DataItem=null;
    4. target element is 'MenuItem' (Name='');
    5. target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')

    所以从头开始:

    • #5 告诉您哪个属性包含失败的绑定。在你的情况下,它是HorizontalContentAlignment

    • #4 是包含失败属性的元素,它是一个 MenuItem,没有 Name 属性来识别它

      所以在某处你有一个导致绑定错误的<MenuItem HorizontalContentAlignment="{Binding ...}" />

    • #3 是目标元素后面的DataItemDataContext。对您来说似乎是null,但这不是问题,因为看起来您的绑定没有引用DataContext。

      但这确实表明MenuItem 不是常规VisualTree 的一部分,因为通常DataContext 是从父对象继承的。

    • #2 包含实际的绑定错误和有关绑定的信息。它实际上可以进一步分解为多个部分。

      • Cannot find source for binding

      • with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''.

      • BindingExpression:Path=HorizontalContentAlignment;

      “找不到源”表示绑定找不到要绑定的源对象,在您的情况下,该源对象应该是 {RelativeSource AncestorType={x:Type ItemsControl}FindAncestorAncestorLevel=1RelativeSource 的默认值,所以我忽略了这些)

      #2 的最后一部分显示您尝试绑定到的PathHorizontalContentAlignment

    总而言之,在您的代码中某处有一个<MenuItem>,它试图将其HorizontalContentAlignment 绑定到ItemsControl.HorizontalContentAlignment,但绑定找不到ItemsControl

    您正在使用RelativeSource FindAncestor 绑定来查找ItemsControl,它会向上搜索可视化树以找到最接近的ItemsControl,但它没有找到,因此在更高的位置上一定没有ItemsControl VisualTree 层次结构来自MenuItem

    我经常在 ContextMenus 中看到这个问题,因为它们与您的 XAML 代码的其余部分不是同一 VisualTree 的一部分。 (要引用 ContextMenu 附加到的主 VisualTree 中的对象,您可以使用 PlacementTarget 属性,例如 this example

    一旦您了解绑定错误,通常很容易在您的 XAML 中找到它的来源。

    根据我的应用程序大小,我通常会执行以下操作之一:

    • 从绑定错误(在您的情况下为MenuItem)中搜索“目标元素”的应用程序,并查看它们中是否有任何使用绑定设置“目标属性”(HorizontalContentAlignment

    • 从绑定错误 (HorizontalContentAlignment) 中搜索“目标属性”的应用程序以找到导致此问题的绑定

    • 在应用程序中搜索绑定错误中显示的绑定文本中相当独特的内容。在您的情况下,您可以尝试在 {x:Type ItemsControl} 上进行搜索,这将是您的 RelativeSource 绑定的一部分,并且此类短语的搜索结果不应该太多。

    • 使用SnoopWPF Inspector 等第三方工具在运行时跟踪绑定错误。

      我以前只使用过 Snoop,但要使用它,您需要启动应用程序并针对它运行 Snoop 以在应用程序运行时检查应用程序的 VisualTree。然后,您可以通过在搜索栏中键入“MenuItem”之类的内容来搜索 VisualTree,以过滤所有 MenuItems 的 Visual Tree,然后查看它们的属性以找出哪个有绑定错误(HorizontalContentAlignment 属性将为由于绑定错误,以红色突出显示)。

      需要注意的是,如果您的MenuItem 位于ContextMenu 中,那么您需要打开该ContextMenu 才能绘制MenuItems 并显示在Snoop 中。

    【讨论】:

    • Rachel,感谢您抽出宝贵时间整理这些内容。它可能对其他人有用,所以我要为努力投赞成票;)但是,您所说的所有我都知道并且我已经尝试过的事情(除了Snoop-我确实尝试过并且可以不识别问题)。我的问题更倾向于某种机制来识别/定位导致问题的声明,这与堆栈跟踪不同。我最终能够找到问题,但这主要是运气不好..(我会更新问题)。
    • 这个答案只有 4 个(现在是 5 个)赞成票这一事实很好地说明了 SO 多年来的变化。它已被浏览超过 1300 次!为什么人那么小气?该死的模组,删除这条评论,不要删除它,whatevs。
    【解决方案3】:

    System.Windows.Data 错误:4 - 这不是您的问题,这是 WPF 已知的问题。它是相关的组合框/菜单,其项目是动态更改的。 See this。 顺便说一句,您可以忽略此错误,通常应用程序可以正常工作。

    【讨论】:

      【解决方案4】:

      我是 WPF 新手,我遇到了完全相同的错误。虽然我现在已经修复了,但我真的不知道如何......以下是我尝试过的步骤:

      首先,我有:

      1. <Menu>
      2. 2 <ContextMenu> 定义在<ListBox.ItemTemplate>

      我已经尝试过:

      1. 将一个<ContextMenu> 移动到<ListBox.ItemContainerStyle> -> 存在错误
      2. <Menu><ContextMenu><MenuItem> 设置和删除样式HorizontalContentAlignmentVerticalContentAlignment ->存在错误
      3. <ContextMenu><MenuItem>Name属性设置<ListBox.ItemTemplate> -> 没有错误!
      4. 去掉Name属性-> 还是没有错误...
      5. 重新启动 VS -> 错误似乎永远消失了......

      最终,我有

      1. <Menu>
      2. <ContextMenu> 定义在<ListBox.ItemTemplate>
      3. <ContextMenu> 定义在<ListBox.ItemContainerStyle>

      并且没有人设置样式HorizontalContentAlignmentVerticalContentAlignment。并且错误消失了……

      似乎有一些刷新问题。所以,遇到同样问题的朋友可以尝试重启VS或者为<MenuItem>设置Name属性...

      【讨论】:

        猜你喜欢
        • 2015-03-30
        • 2023-03-30
        • 1970-01-01
        • 1970-01-01
        • 2013-09-20
        • 1970-01-01
        • 1970-01-01
        • 2018-02-23
        • 1970-01-01
        相关资源
        最近更新 更多