Объекты WPF Sentinel и как проверить внутренний тип
Как некоторые из вас обнаружили, появилась новая функция (?) WPF 4, где механизм привязки данных может передавать ваши экземпляры пользовательских элементов управления класса MS.Internal.NamedObject с именем "{DisconnectedItem}" в DataContext - вместо элемент данных, ожидаемый вашим кодом (это происходит, когда шаблонный элемент управления отключен его ItemsControl). Это так называемые дозорные объекты.
В существующем коде это может привести к ложным исключениям, когда код для него не подготовлен. Они могут быть поглощены подсистемой привязки данных или могут нанести ущерб. Следите за консолью отладки.
Во всяком случае, я узнал об этом на этом форуме MSDN. И есть пост Сэма Бента, который объясняет все это. Иди прочитай это сейчас, ты захочешь это знать. Суть в том, что эти события никогда не должны были запускаться (это ошибка), поэтому:
Игнорируйте событие 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}";
}
(или что-то, что работает). Я также последовал предложению Сэма кэшировать объект для последующих проверок на равенство ссылок (это одиночный код).
Конечно, это означает, что у меня нет проблем, на самом деле. Но мне любопытно, и эта публикация наверняка принесет пользу некоторым пользователям, поэтому все равно стоит спросить:
Есть ли способ, которым я могу точно проверить тип по внутреннему типу NamedObject, не прибегая к сравнению строк?
2 ответа
Вот этот?
var disconnectedItem = typeof(System.Windows.Data.BindingExpressionBase)
.GetField("DisconnectedItem", BindingFlags.Static | BindingFlags.NonPublic)
.GetValue(null);
В.NET 4.5 теперь можно сравнить с BindingOperations.DisconnectedSource
,