WPF Sentinel对象以及如何检查内部类型

时间:2010-10-06 00:39:14

标签: c# .net wpf data-binding wpf-4.0

正如你们中的一些人所发现的那样,新功能(?)出现在WPF 4中,其中数据绑定引擎可以传递类名为“strong> MS.Internal.NamedObject 的自定义控件实例” {DisconnectedItem} “进入DataContext - 而不是您的代码所期望的数据项(当模板控件被其ItemsControl断开时会发生这种情况)。这些被称为哨兵对象。

在现有代码中,这可能导致虚假异常,其中代码没有准备好。这些可以被数据绑定子系统吞噬,或者它们可能造成严重破坏。请密切关注您的调试控制台。

无论如何,我在this MSDN forum上了解到了这一点。还有Sam Bent的帖子explains it all。现在去阅读,你想知道这个。本质上是这些事件永远不会被解雇(这就是错误),所以:

  

如果忽略DataContextChanged事件   DataContext是一个标记对象。

所以,我想检查一下我的DataContext。但是怎么样?考虑:

public bool IsSentinelObject(object dataContext)
{
    return (dataContext is MS.Internal.NamedObject);
}

猜猜会发生什么?它没有编译,因为MS.Internal.NamedObject是内部的,我无法访问。当然,我可以像这样破解它:

public bool IsSentinelObject(object dataContext)
{
    return dataContext.GetType().FullName == "MS.Internal.NamedObject"
           || dataContext.ToString() == "{DisconnectedObject}";
}

(或其他有用的东西)。我也遵循了Sam的建议来缓存对象以供以后引用相等性检查(它是一个单例)。

当然,这意味着我没有问题,不是真的。但我很好奇,这篇文章肯定会让一些用户受益,所以无论如何都值得问:

有没有办法可以根据内部NamedObject类型检查类型,而无需求助于字符串比较?

2 个答案:

答案 0 :(得分:25)

在.NET 4.5中,您现在可以与 BindingOperations.DisconnectedSource 进行比较。

答案 1 :(得分:16)

这一个?

var disconnectedItem = typeof(System.Windows.Data.BindingExpressionBase)
    .GetField("DisconnectedItem", BindingFlags.Static | BindingFlags.NonPublic)
    .GetValue(null);