正如一些人已经发现的那样,WPF 4 中出现了一个新功能(?)——数据绑定引擎可能会将名为"{DisconnectedItem}"的MS.Internal.NamedObject类实例传递到DataContext中,而不是你的代码所期望的数据项(当模板控件被其ItemsControl断开连接时会发生这种情况)。这些被称为哨兵对象。
在现有代码中,这可能会导致意外异常,因为代码没有准备好处理它。这些异常可能被数据绑定子系统吞噬,也可能会造成严重问题。请注意您的调试控制台。
无论如何,我是从这个 MSDN 论坛了解到这一点的。Sam Bent 的帖子解释了所有内容。现在就去读一下,你会想知道这些的。要点是这些事件本不应该被触发(这是个错误),所以:
如果DataContext是哨兵对象,请忽略DataContextChanged事件。
那么,我想检查我的DataContext。但如何呢?考虑以下内容:
public bool IsSentinelObject(object dataContext)
{
return (dataContext is MS.Internal.NamedObject);
}
你猜会发生什么?它无法编译,因为 MS.Internal.NamedObject 是 internal 的,无法被我访问。当然,我可以像这样进行 hack:
public bool IsSentinelObject(object dataContext)
{
return dataContext.GetType().FullName == "MS.Internal.NamedObject"
|| dataContext.ToString() == "{DisconnectedObject}";
}
(或其他工作的东西)。我还遵循了Sam的建议,缓存该对象以供稍后参考相等性检查(它是一个单例)。
当然,这意味着我没有问题,不是真的。但我很好奇,这篇文章肯定会使一些用户受益,所以问问也值得:
有没有一种方法可以精确地检查内部NamedObject类型,而不必使用字符串比较?
DataContextChanged
在.NET 4.5中不再被触发,当传递{DisconnectedObject}时会出现此问题。详见:https://connect.microsoft.com/VisualStudio/feedback/details/619658/wpf-virtualized-control-disconnecteditem-reference-when-datacontext-switch。 - Steven JeurisDataContext
绑定到DataContext
的内部元素(视图模型组合)时,我仍然在.NET 4.5中遇到类似的问题。解决方法是简单地防止这样做,而是更新所有绑定路径到InnerElement.[whathever]
。 - Steven Jeuris