Как стать автором
Обновить

Flex. Привязка XML данных (Data Binding) без использования MXML.

Темой статьи стала проблема, с которой я столкнулся, разрабатывая некоторый продукт на Flex'е.

Начнем. Как можно привязать XML данные к некоторому значению визуального компонента... В общем-то не сложно:
[Bindable]<br/>
private var some_xml_data: XML;

и MXML'ом привязуем его к компоненту:
<some_component some_property="{some_xml_data}/>

Когда изменяется some_xml_data то some_property в some_component'а тоже меняется... 
Припустим компонент some_component создает динамически еще некоторые компоненты,
которым передается некоторая выборка из some_property some_component'а:
var dynamic_component: DynamicComponent = new DynamicComponent();<br/>
dynamic_component.some_other_property = some_property.item.(@name=='name')[0];<br/>

Итак постает вопрос - как сделать так чтобы data binding в dynamic_component тоже работала?
BindingUtils.bindProperty(dynamic_component, 'some_other_property', some_property.item.(@name=='name'), '0');

Результат - some_other_property меняется только 1 раз, когда вызывается метод bindProperty,
последующие изменения в some_xml_data никак не влияют. В документации и гугле я ничего не нарыл…
Поковырявшись  пару часов в том что генерирует Flex Builder выяснилось следующее
(привожу в пример код, в ходе буду объяснять):
//импорт необходимых классов<br/>
//точного их описания не дам, так как все что я нашел, это исходники классов,<br/>
//которых нет в документации<br/>
import mx.binding.Binding;<br/>
<br/>
import mx.binding.PropertyWatcher;<br/>
import mx.binding.XMLWatcher;<br/>
<br/>
//исходное свойство<br/>
<br/>
[Bindable]<br/>
private var src_prop: XML = <br/>
  <root><br/>
<br/>
    <item0><br/>
      <item1 name="some name" /><br/>
    </item0><br/>
<br/>
  </root>;<br/>
<br/>
//результирующее свойство<br/>
private var dest_prop: XML;<br/>
 <br/>
//функция которая связывает dest_prop как dest_prop = src_prop..item1.@name<br/>
private function bindProp(): void {<br/>
<br/>
  var binding:Binding;<br/>
//Создает объект для связывания.<br/>
// public function Binding(document:Object, srcFunc:Function,<br/>
//                           destFunc:Function, destString:String)<br/>
//document - это документ, который является целью всей этой работы ( не очень звучит) ).<br/>
//  (в большинстве случаев это будет this)<br/>
//srcFunc - это функция, которая возвращает значение которое <br/>
// задается результирующему свойству<br/>
//destFunc - функция, которая будет принимать значения<br/>
//  и назначать его результирующему свойству.<br/>
//destString - наименование результирующего свойства, которое предоставляется в виде строки <br/>
<br/>
  binding = new Binding(<br/>
    this,<br/>
    function(): * {<br/>
      return src_prop..item1.@name;<br/>
    },<br/>
    function(_sourceFunctionReturnValue:*):void {<br/>
      dest_prop = _sourceFunctionReturnValue;<br/>
    },<br/>
    'dest_prop'<br/>
  );<br/>
 <br/>
//PropertyWatcher - нужен если заменяется значение свойства<br/>
//public function PropertyWatcher(propertyName:String,<br/>
//                                events:Object,<br/>
//                                listeners:Array,<br/>
//                                propertyGetter:Function = null)<br/>
//propertyName - наименование свойства для просмотра.<br/>
//events - события которые указывают что свойство изменилось <br/>
//  (в данном случае это {propertyChange: true}).<br/>
//listeners - массив Binding объектов, которые слушают этот Watcher.<br/>
//propertyGetter - функция-помощник которая используется для доступа <br/>
//  непубличный переменных.<br/>
  var watcher: PropertyWatcher = new PropertyWatcher(<br/>
    'src_prop', <br/>
    {propertyChange: true},<br/>
    [binding],<br/>
    function(propertyName:String):* {return this[propertyName];}<br/>
  );<br/>
   watcher.updateParent(this);<br/>
//XMLWatcher - нужен если меняется значение какой то ветки XML'а<br/>
//addChild - добавляет watcher'a, который будет наблюдать за <br/>
//  измениями внутри свойства.<br/>
  watcher.addChild(new XMLWatcher('item1', [binding]));<br/>
<br/>
//исполняет присваивание dest_prop = src_prop..item1.@name<br/>
  binding.execute();<br/>
}


Также можно связать данные не только с XML а и с другими типами данных
используя следующие классы с Flex SDK пакета mx.binding:
ArrayElementWatcher<br/>
FunctionReturnWatcher<br/>
RepeaterComponentWatcher<br/>
RepeaterItemWatcher<br/>
StaticPropertyWatcher


Надеюсь, данная публикация поможет людям, которые столкнулись с этой проблемой.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.