#c# #.net #wpf #xaml #markup-extensions
#c# #.net #wpf #xaml #разметка-расширения
Вопрос:
Я пишу пользовательское расширение разметки. В его ProvideValue
методе я хотел бы изменить / преобразовать возвращаемое значение на основе предполагаемого целевого типа свойства, для которого используется расширение разметки для предоставления значения.
(В принципе, a TypeConverter
знает о целевом типе окружающей его привязки и может соответствующим образом адаптировать свое поведение; я хотел бы сделать то же самое в моем расширении разметки.)
Теперь ProvideValue
метод получает только IServiceProvider
в качестве аргумента. Кажется, я должен быть в состоянии использовать его для получения объекта, который предоставляет мне желаемый бит контекстной информации, но пока ни одна из моих попыток сделать это не была полностью удовлетворительной:
-
Я извлек
IDestinationTypeProvider
реализацию. Хотя кажется, что он делает именно то, что мне нужно, основываясь на его имени, к сожалению, он выдает исключение:var dtp = (IDestinationTypeProvider)serviceProvider.GetService(typeof(IDestinationTypeProvider)); var destType = dtp.GetDestinationType(); // NullReferenceException on this line
-
Я извлек
IProvideValueTarget
реализацию. Он предоставляет мне целевое свойство, но только какSystem.Object
, так что, похоже, я должен сам подготовить свой код для обработки различных (?) типов свойств и получения типа самостоятельно.
Каким предполагаемым способом расширение разметки может получить свой целевой тип?
Ответ №1:
Используйте IServiceProvider
, чтобы получить IProvideValueTarget
, затем посмотрите на TargetProperty
, который должен (но не гарантировано) быть DependencyProperty
.
var provideValueTarget = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
var propertyType = (provideValueTarget.TargetProperty as DependencyProperty)?.PropertyType;
// Test propertyType for null
Целевым свойством также может быть an, EventInfo
если MarkupExtension используется с событием, или a MethodInfo
если оно используется с присоединенным событием (или, как вы указали в комментариях, a PropertyInfo
если оно используется с обычным свойством).
К сожалению, я думаю, что это единственный способ сделать это. DynamicResourceExtension
имеет аналогичные проверки, смотрите здесь и здесь — если бы был лучший API, я предполагаю, что он использовал бы его.
Комментарии:
1. Или
PropertyInfo
если расширение разметки используется в обычном свойстве (не зависящем). Или что-то совершенно другое в будущей версии фреймворка. Я надеялся, что BCL избавит меня от этого, но если это действительно единственный способ, я собираюсь принять этот ответ немного позже.2. @O.R.Mapper Я почти уверен, что это единственный способ сделать это, к сожалению. Я добавил ссылку на некоторый код WPF, который выполняет те же проверки. Если вам удастся найти лучший способ, я буду рад!