问题描述
我有问题
可以用以下xaml复制它:
It can be reproduced with following xaml:
<Window PreviewKeyDown="Window_PreviewKeyDown"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
... >
<Window.Resources>
<DataTemplate DataType="{x:Type local:ViewModel}">
<ListBox ItemsSource="{Binding List}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Width="20" Height="20">
<Border.Background>
<SolidColorBrush Color="{Binding diag:PresentationTraceSources.TraceLevel=High}" />
</Border.Background>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</Window.Resources>
<ContentControl Content="{Binding}" />
</Window>
和cs:
public class ViewModel
{
public List<Color> List { get; } = new List<Color> { Colors.Red, Colors.Blue, Colors.Green, Colors.Black, Colors.Yellow };
}
public partial class MainWindow : Window
{
readonly ViewModel _vm = new ViewModel();
public MainWindow()
{
InitializeComponent();
}
void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.F1)
DataContext = _vm;
if (e.Key == Key.F2)
DataContext = null;
}
}
开始,按并检查 Output
窗口(绑定跟踪已启用,因此您将看到更多).
Start, press and check Output
window (binding tracing is enabled, so you will see more).
问题:我该如何解决?
错误不会导致功能出现问题,但是它们会出现在 Output
窗口中(在实际项目中有很多错误),这已经表明存在一些问题.哪个问题?
Errors doesn't cause problem to functionality, but they appears in Output
window (and in real project there are lots of them), which already a sign of some problem. Which problem?
这里的关键是要有数据模板并在一段时间后应用,然后在数据模板中进行绑定会引起问题.在构造函数中设置 DataContext
不会引起问题.
Key here is to have datatemplate and apply it some time later, then this binding in datatemplate will cause problems. Setting DataContext
in constructor doesn't cause problems.
如果有人能够理解并可以提供一些有关以下内容的提示,则这里有一些痕迹:
Here is some trace, if someone is able to understand it and can give some hints regarding:
System.Windows.Data Warning: 56 : Created BindingExpression (hash=45377043) for Binding (hash=28932383)
System.Windows.Data Warning: 58 : Path: ''
System.Windows.Data Warning: 60 : BindingExpression (hash=45377043): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=45377043): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=45377043): Attach to System.Windows.Media.SolidColorBrush.Color (hash=48519443)
System.Windows.Data Warning: 64 : BindingExpression (hash=45377043): Use Framework mentor <null>
System.Windows.Data Warning: 67 : BindingExpression (hash=45377043): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=45377043): Framework mentor not found
System.Windows.Data Warning: 65 : BindingExpression (hash=45377043): Resolve source deferred
...
System.Windows.Data Warning: 67 : BindingExpression (hash=45377043): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=45377043): Framework mentor not found
System.Windows.Data Warning: 67 : BindingExpression (hash=45377043): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=45377043): Framework mentor not found
System.Windows.Data Warning: 67 : BindingExpression (hash=45377043): Resolving source (last chance)
System.Windows.Data Warning: 69 : BindingExpression (hash=45377043): Framework mentor not found
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:(no path); DataItem=null; target element is 'SolidColorBrush' (HashCode=48519443); target property is 'Color' (type 'Color')
我理解它是什么,当datatemplate创建元素时,找不到用于绑定到源的 mentor (什么是mentor?),所以推迟了绑定创建.然后重复几次,并由于给定的错误而失败.但是,最后它起作用了,也许它一直在重复而不追踪它?有什么想法吗?
I understand it what when datatemplate creates elements, mentor for binding to source is not found (what is mentor?), so binding creating is deffered. Then it repeats few times and fails with given error. But then it works at the end, perhaps it continues repeating without tracing it? Any ideas?
推荐答案
不幸的是,我无法为您提供有关发生绑定错误的原因以及绑定最终起作用的确切细节,但是也许我可以为您提供一些启示.
Unfortunately I cannot give you exact specifics on why the binding error occurs and why the binding ultimately works, but perhaps I'll be able to shed some light on it.
这似乎正在发生:
由于使用绑定时未指定来源,因此默认情况下,框架尝试使用目标上的 FrameworkElement.DataContext
或 FrameworkContentElement.DataContext
属性作为源为绑定.这显然是失败的,因为 SolidColorBrush
都不是从这两个派生的.此外,由于 SolidColorBrush
既不是可视树也不是逻辑树的一部分,因此它不能绑定到 Border
,因此框架无法解析绑定的来源.不确定在某个时候源已解析并且绑定正常工作是怎么回事.
Because you're using a binding without specifying a source, by default the framework tries to use FrameworkElement.DataContext
or FrameworkContentElement.DataContext
property on the target as the source for the binding. That obviously fails because SolidColorBrush
derives from neither. Moreover, since SolidColorBrush
is not part of the visual tree nor the logical tree, it cannot be tied back to the Border
, hence the framework cannot resolve the source for the binding. Not sure though how it happens that at some point the source is resolved and the binding is working correctly.
但是,有一个针对此问题的解决方案,该解决方案是专门为解决此类情况而引入的,并且使用可视化或逻辑树以外的其他方式来解析绑定源.您需要做的就是将 SolidColorBrush
定义为资源:
There is however a solution to this problem, which was introduced specifically to address this kind of situations, and which uses other means than visual or logical tree to resolve binding sources. All you need to do is to define your SolidColorBrush
as a resource:
<Border Width="20" Height="20">
<Border.Resources>
<SolidColorBrush x:Key="BackgroundBrush" Color="{Binding}" />
</Border.Background>
<Border.Background>
<StaticResource ResourceKey="BackgroundBrush" />
</Border.Background>
</Border>
这样做,您会在跟踪中获得一个主要区别,这似乎是避免出现 Error:2
:
By doing so you get one major difference in the trace which seems to be the key to not getting the Error: 2
:
...
System.Windows.Data Warning: 65 : BindingExpression (hash=38517915): Resolve source deferred
System.Windows.Data Warning: 95 : BindingExpression (hash=38517915): Got InheritanceContextChanged event from SolidColorBrush (hash=55584612)
...
此解决方案不仅适用于 SolidColorBrush
,而且适用于源自 Freezable
的任何类型的对象(画笔,变换等)
This solution is applicable not only to SolidColorBrush
, but to any object of type deriving from Freezable
(brushes, transforms, etc.)
尽管如此,您必须要小心,因为这会有所不同,您将资源放置在 Freezable
的资源字典中.如果将其放置在 Window.Resources
词典中,则源将解析为 Window.DataContext
(在您的情况下为 ViewModel
实例).
You have to be careful though because it makes a difference in which resource dictionary you place your Freezable
. If you were to place it in the Window.Resources
dictionary the source would resolve to Window.DataContext
(a ViewModel
instance in your case).
我最后的假设是,如果您使用此技术,则解析在您的 Freezable
上设置的绑定就像在资源字典所有者上设置的一样(由我认为称为 mentor 或 governing 元素的方式).这也适用于使用 RelativeSource
或 ElementName
的绑定.
My final hypothesis is that if you use this technique, the bindings set on your Freezable
are resolved as if they were set on the resource dictionary owner (which by the way I believe is referred to as mentor or governing element). That also applies to bindings using RelativeSource
or ElementName
.
这篇关于Datatemplate绑定垃圾邮件输出窗口出现错误:找不到管理FrameworkElemen的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!