Pull to refresh

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


Надеюсь, данная публикация поможет людям, которые столкнулись с этой проблемой.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.