Объекты WPF Sentinel и как проверить внутренний тип - PullRequest
27 голосов
/ 06 октября 2010

Как некоторые из вас обнаружили, появилась новая функция (?) 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 ]

25 голосов
/ 06 июня 2014

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

16 голосов
/ 06 октября 2010

Этот?

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