Объекты WPF Sentinel и проверка внутреннего типа

как некоторые из вас обнаружили, новая функция (?) появился WPF 4, где обработчик привязки данных может передать ваши экземпляры пользовательского элемента управления класса госпожа внутренняя.NamedObject С именем " {DisconnectedItem} " в DataContext-вместо элемента данных, ожидаемого вашим кодом (это происходит, когда шаблонный элемент управления отключается его ItemsControl). Они называются объектами sentinel.

в существующем коде это может привести к ложному исключения, когда код не готов к этому. Они могут быть поглощены подсистемой привязки данных,или они могут нанести ущерб. Следите за своей консолью отладки.

в любом случае, я узнал об этом в этот форум MSDN. И есть столб Сэма Бента, который объясняет все. Иди и прочти его сейчас,вы хотите знать это. Суть в том, что эти события никогда не должны были срабатывать (это ошибка), поэтому:

игнорировать событие DataContextChanged, если DataContext является объектом sentinel.

Итак, я хочу проверить свой DataContext. Но как? Подумайте:

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

угадайте, что происходит? Он не компилируется, потому что внутренняя г-жа.NamedObject является внутренним и недоступным для меня. Конечно, я могу взломать его так:

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

(или что-то, что работает). Я также последовал предложению Сэма кэшировать объект для последующих проверок равенства ссылок (это одиночка.)

конечно, это означает, что у меня нет проблем, не правда. Но мне любопытно, и эта публикация обязательно принесет пользу некоторым пользователям, поэтому в любом случае стоит спросить:

есть ли способ точно проверить тип по внутреннему типу NamedObject, не прибегая к сравнениям строк?

2 ответов


этот?

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

в .NET 4.5 теперь вы можете сравнить с BindingOperations.DisconnectedSource.