Smart tag – Single Binding

Intro

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

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

Я собираюсь рассказать и показать, как создать такую же функциональность в смарт тэге, которую вы наблюдаете при задании биндинга в окне свойств.

Реализовав этот функционал, вы сможете сэкономить много времени, которое раньше тратилось на путешествия по окну свойств для того, чтобы настроить поведение компонента.

Есть ли стандартный способ задания биндинга?

Я его не нашел. Поиски «простого» и короткого стандартного способа не увенчались успехом. Sad, but true. Используя гугл, я нашел только 4 (четыре) вопроса по теме, и те без ответов. Только раз было направление для поисков, но для Web форм. Расстройству моему не было предела, но недолго оно длилось! Если кто-то что-то смог сделать, то другой человек может это сделать тоже. Руководствуясь этим железобетонным принципом, я вспомнил, что Microsoft опубликовала исходные коды для .Net фреймворка и потратив некоторое время на поиски я нашел где их слить и начал детальное исследование.

Используя свои знания по разработке компонентов и опыту работы с ними, я начал поиски с реализации ComboBox, чтобы посмотреть какой дизайнер используется для биндинга. К сожалению, там не оказалось какого-то общего дизайнера который можно было бы сразу прикрутить и получить профит. Но в целом это не было проблемой. Я нашел такие строчки:

Можете поискать в MSDN что пишут по поводу DesignBindingEditor в общем поиске и по коду. Что?  А? Пишут, что ничего нет?

Ну ладно, редактор и конвертор типов должны все равно быть стандартными и найти их проблемой быть не должно. Но это не все, иначе было бы слишком легко! ))

Копи-паста

Это наш путь к пониманию сути вещей (если нет документации). Скопировать, вставить, немного менять код и смотреть как и что меняется. Да, метод научного тыка.

Как вы должны помнить, свойства, объявленные в классе дизайнера смарт тэга, будут потом использоваться для отображения пользователю и весь рабочий код помещается в “get”/“set”. Здесь много всего написано, что даже чуток пугает. =)

Вау!

Начнем разбор полетов со свойства «get». В строке номер 3 берутся все элементы составляющие компонент и ищутся биндинги с необходимыми именами. Для ComboBox это будет SelectedValue. Если ничего не найдено, значит биндинг еще не назначался на данное поле. Иначе, с помощью DesighnBindingConverter, берутся свойства dataMember и dataSource для создания строкового представления биндинга.

В результате экспериментов «get» оказался легкой частью для адаптации. Больше всего проблем возникло с «set». Если биндинг был уже назначен, то он в смарт тэге представлялся в виде строки, которую надо было разобрать (распарсить). Для этого использовалась первая часть выражения if. И в этой части, мне кажется и кроется причина почему же биндиг одиночного поля не опубликован в свободном доступе. В строке номер 21 создается EditorServiceContext, который является внутренним классом в .Net. Придется его найти и «переписать» для наших нужд. Все переписывание конечно свелось к копи-пасте в локальный проект. Последнее выражение с SetSelectedValueBinding так же было скопировано без изменений.

Рефакторинг

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

Получилось более ясно и просто. Можно использовать не задумываясь для других компонентов. В данном случае первый параметр указывает на свойство в связанном со смарт тэгом компоненте.

GetBind и SetBind объявлены в классе ControlActionListBase. Э том случае ActionList наследуем от ControlActionListBase, а ControlActionListBase от DesignerActionList.

Таким образом, в нашем классе MyControlActionList остаются только значимый код для конкретного смарт тэга, что упростит дальнейшую редакцию и чтение. Весь служебный, общий код вынесен в базу. Написал и забыл. ;) Когда вы примените биндинг с помощью описанного кода через смарт тэг, в экземпляре компонента будет сгенерирован код похожий на этот:

Все по-честному!

Финальный результат можно посмотреть в исходниках.

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

Hard’n’heavy!

Оставить комментарий