Объекты 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);