有没有办法确定WPF绑定在哪里声明/创建? [英] Is there a way to determine where a WPF Binding is declared/created?

查看:106
本文介绍了有没有办法确定WPF绑定在哪里声明/创建?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个项目正在抛出一些数据绑定错误。一个例子是:



System.Windows.Data错误:4:找不到引用RelativeSource FindAncestor,AncestorType ='System的绑定源。 Windows.Controls.ItemsControl',AncestorLevel ='1''。 BindingExpression:Path = Horizo​​ntalContentAlignment; DataItem = null; target元素是'MenuItem'(Name ='');目标属性是Horizo​​ntalContentAlignment(类型'Horizo​​ntalAlignment')



我的问题是是否有一种方法可以确定此绑定实际声明的位置(或者在XAML或代码中声明)。



我迄今为止所尝试过的:




  • 为System.Windows.Data命名空间添加了一个调试跟踪,级别为o All;这并没有产生任何更有用的信息

  • 尝试在项目中为文字搜索绑定,希望找到所有具有路径的绑定表达式设置为 Horizo​​ntalContentAlignment ;我发现只有一个,并删除它,但我仍然得到的消息,似乎表明这不是错误的一个..



你知道任何其他的技巧,使WPF吐出一些更为有用的信息,这个绑定声明在哪里?



更新



经过一些更多的搜索,我很确定这是由一种风格应用于 MenuItem 引起的。但是,我仍然无法明确指出错误的绑定被声明的位置。



更新2



我发现问题。然而,问题仍然存在,因为发现问题主要是基于错误消息中有限的信息在黑暗中进行搜索的问题。



事实证明,绑定在样式中声明。风格不在我的应用程序。这可能是 MenuItem 的默认样式。所以要解决这个问题,现在我只需手动在 MenuItems 中设置 Horizo​​ntalContentAlignment 。错误的原因与操作顺序有关,因为 MenuItem 在代码中生成。我会分别发布一个新的问题。



所以,现在,故事的道德是,我觉得需要一个更好的机制来确定其中声明了错误的绑定。我想看到类似堆栈跟踪绑定的东西..



如果有人知道任何其他工具,我会保留一段时间更长的时间或确定在代码或标记中声明绑定的地方的方法。



我已经发布了另一个 MenuItems 这里的样式/绑定问题/ / menuitem-added-program -atically-causes-binding-error>

解决方案

当调试WPF绑定错误时,我发现最容易用分号分解错误,从头开始


  1. System.Windows.Data错误:4:

  2. 找不到用于引用'RelativeSource FindAncestor,AncestorType ='System.Windows.Controls.ItemsControl',AncestorLevel ='1'的绑定源。 BindingExpression:Path = Horizo​​ntalContentAlignment;

  3. DataItem = null;

  4. target元素是'MenuItem'(Name ='');

  5. target属性是'Horizo​​ntalContentAlignment '(类型'Horizo​​ntalAlignment')

所以从最后开始:




  • #5告诉你什么属性包含失败的绑定。在你的情况下,它是 Horizo​​ntalContentAlignment


  • #4是包含失败属性的元素, MenuItem 没有名称属性以通过



    所以在某个地方你有一个< MenuItem Horizo​​ntalContentAlignment ={Binding ...}/> 导致绑定错误。


  • #3是目标元素后面的 DataItem DataContext 。它似乎是 null ,但这不是一个问题,因为它看起来像你的绑定没有引用DataContext。



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


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




    • 找不到绑定的来源


    • ''。


    • BindingExpression:Path = Horizo​​ntalContentAlignment;




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



    #2的最后一部分显示您尝试绑定到的路径 Horizo​​ntalContentAlignment




所以要把它放在一起,代码中的某个地方有一个< MenuItem> 它试图将其 Horizo​​ntalContentAlignment 绑定到一个 ItemsControl.Horizo​​ntalContentAlignment ,但绑定找不到 ItemsControl



您正在使用 RelativeSource FindAncestor 绑定找到 ItemsControl ,它搜索视觉树,找到最接近的 ItemsControl ,并没有找到一个所以在 MenuItem 中的VisualTree层次结构中,必须没有 ItemsControl



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



一旦你明白了绑定错误,它通常很容易找到你的XAML中的源代码。



根据我的应用程序大小,我通常会做一个以下内容:




  • 从绑定错误中搜索应用程序中的目标元素(在您的情况下, MenuItem ),看看是否有任何一个用绑定设置目标属性( Horizo​​ntalContentAlignment ) / li>

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


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


  • 使用第三方工具,如 Snoop WPF检查器在运行时跟踪绑定错误。



    我以前只使用过Snoop,但是要使用它,您需要启动应用程序并运行Snoop它在运行时检查应用程序的VisualTree。然后,您可以通过在搜索栏中输入MenuItem来搜索VisualTree,以便为所有 MenuItems 过滤Visual Tree,然后查看其属性,找出哪一个具有绑定错误( Horizo​​ntalContentAlignment 属性将由于绑定错误而突出显示为红色)。



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



I have a project which is throwing some data binding errors. One example is:

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')

My question is whether there is a way to determine where this binding is actually declared (either it is declared in XAML or in code).

What I've tried so far:

  • added a debug trace for the System.Windows.Data namespace with level set o All; this did not produce any more useful information
  • tried doing a text-search in the project for the word Binding in hopes of locating all binding expressions that have the Path set to HorizontalContentAlignment; I found only one and removed it but I'm still getting the message which seems to indicate that that was not the faulty one..

Do you know of any other tricks to make WPF spit out some more useful information about where exactly is this binding declared?

UPDATE

After a little bit more searching I'm pretty sure this is somehow caused by a style being applied to a MenuItem. However, I'm still not able to pin-point the location where the faulty binding is being declared..

UPDATE 2

I found the problem. However the question still remains since finding the issue was mostly a matter of searching in the dark based on the limited info in the error message.

As it turns out, the binding is declared in a style. And the style is not in my application. It's probably the default style for MenuItem. So to fix the issue for now I've just manually set the HorizontalContentAlignment on all MenuItems. The reason for the error is somehow related to order of operations as this MenuItem is generated in code. I'll post a new question on that separately.

So, for now, the moral of the story is that I feel that there needs to be a better mechanism to determine where the faulty binding is declared. I'd like to see something like a stack trace for bindings..

I'm keeping the question open for a little while longer in case somebody knows of any other tools or methods of determining the place where a binding is declared in code or markup.

I've posted another question regarding the style/binding being applied to the MenuItems here.

解决方案

When debugging WPF binding errors, I find it easiest to break up the error by the semicolons, and start from the end

  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')

So starting from the end:

  • #5 tells you what property contains the binding that is failing. In your case, it's HorizontalContentAlignment

  • #4 is the element containing the failing property, which is a MenuItem without a Name property to identify it by

    So somewhere you have a <MenuItem HorizontalContentAlignment="{Binding ...}" /> that is causing the binding error.

  • #3 is the DataItem, or DataContext, that is behind the target element. It appears to be null for you, but that's not a problem since it looks like your binding isn't referencing the DataContext.

    But this does suggest that the MenuItem is not part of your regular VisualTree, since typically the DataContext is inherited from the parent object.

  • #2 contains the actual binding error and information about the binding. It can actually be further broken up into multiple parts.

    • Cannot find source for binding

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

    • BindingExpression:Path=HorizontalContentAlignment;

    "Cannot find source" means the binding can't find the source object to bind to, and in your case, that source object should be {RelativeSource AncestorType={x:Type ItemsControl} (FindAncestor and AncestorLevel=1 are defaults for a RelativeSource, so I'm ignoring those)

    And the last part of #2 shows the Path you are trying to bind to: HorizontalContentAlignment

So to put it all together, somewhere in your code there is a <MenuItem> which is trying to bind its HorizontalContentAlignment to an ItemsControl.HorizontalContentAlignment, but the binding can't find the ItemsControl.

You're using a RelativeSource FindAncestor binding to find the ItemsControl, which searches up the visual tree to find the closest ItemsControl, and it's not finding one so there must be no ItemsControl higher up in the VisualTree hierarchy from the MenuItem.

I often see this problem with ContextMenus because they are not part of the same VisualTree as the rest of your XAML code. (To reference the object in the main VisualTree that a ContextMenu is attached to, you can use the PlacementTarget property, like this example.

Once you understand the binding error, its often easy to find the source of it in your XAML.

Depending on my application size, I usually do one of the following:

  • Search the application for the "target element" from the binding error (in your case, MenuItem), and see if any of them are setting the "target property" (HorizontalContentAlignment) with a binding

  • Search the application for the "target property" from the binding error (HorizontalContentAlignment) to find the binding causing this problem

  • Search the application for something fairly unique from the binding text shown in the binding error. In your case, you could try searching on {x:Type ItemsControl} which would be part of your RelativeSource binding, and there shouldn't be too many search results for such a phrase.

  • Use a 3rd party tool like Snoop or WPF Inspector to track down the binding error at run time.

    I've only used Snoop before, but to use it you need to startup your application and run Snoop against it to inspect your application's VisualTree while it's running. You can then search the VisualTree by typing something like "MenuItem" in the search bar to filter the Visual Tree for all MenuItems, then look through their properties to find out which one has a binding error (the HorizontalContentAlignment property will be highlighted in red because of the binding error).

    It should be noted that if if your MenuItem is inside a ContextMenu, then you need to open that ContextMenu for the MenuItems to be drawn and show up in Snoop.

这篇关于有没有办法确定WPF绑定在哪里声明/创建?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆