Сведения о вопросе

Fhohir

08:53, 20th August, 2020

Теги

Flex: существует ли безболезненная программная привязка данных?

Просмотров: 435   Ответов: 4

До сих пор я только немного занимался разработкой Flex, но я предпочитал подход создания элементов управления программно над файлами mxml, потому что (и , пожалуйста, поправьте меня, если я ошибаюсь!) Я понял, что вы не можете иметь его в обоих направлениях-то есть иметь функциональность класса в отдельном файле класса ActionScript, но иметь содержащиеся элементы, объявленные в mxml.

С точки зрения производительности разница невелика, но программная привязка данных кажется несколько менее тривиальной. Я посмотрел, как компилятор mxml преобразует выражения привязки данных. В результате получается куча сгенерированных обратных вызовов и гораздо больше строк, чем в представлении mxml. Итак, вот в чем вопрос: есть ли способ сделать привязку данных программно, которая не включает в себя мир боли?



  Сведения об ответе

VCe znayu

07:24, 4th August, 2020

Не бойтесь MXML. Он отлично подходит для размещения видов. Если вы пишете свои собственные повторно используемые компоненты, то запись их в ActionScript может иногда дать вам немного больше контроля, но для не повторно используемых представлений MXML гораздо лучше. Он более лаконичен,привязки чрезвычайно просты в настройке и т. д.

Однако привязки в pure ActionScript не должны быть такой уж большой болью. Это никогда не будет так просто, как в MXML, где многое делается для вас, но это может быть сделано не слишком много усилий.

То, что у вас есть-это BindingUtils , и это методы bindSetter и bindProperty . Я почти всегда использую первое, так как обычно хочу сделать какую-то работу или вызвать invalidateProperties , когда значения меняются, я почти никогда не хочу просто установить свойство.

Что вам нужно знать, так это то , что эти два возвращают объект типа ChangeWatcher, если вы хотите удалить привязку по какой-то причине, вы должны держаться за этот объект. Это то, что делает ручные привязки в ActionScript немного менее удобными, чем в MXML.

Давайте начнем с простого примера:

BindingUtils.bindSetter(nameChanged, selectedEmployee, "name");

Это создает привязку, которая будет вызывать метод nameChanged , когда свойство name объекта в переменной selectedEmployee изменяется. Метод nameChanged получит новое значение свойства name в качестве аргумента, поэтому он должен выглядеть следующим образом:

private function nameChanged( newName : String ) : void 

Проблема с этим простым примером заключается в том, что после настройки этой привязки она будет срабатывать каждый раз, когда изменяется свойство указанного объекта. Значение переменной selectedEmployee может измениться, но привязка по-прежнему настроена для объекта, на который указывала переменная ранее.

Есть два способа решить эту проблему: либо сохранить ChangeWatcher , возвращаемый BindingUtils.bindSetter , и вызвать unwatch на нем, когда вы хотите удалить привязку (а затем настроить вместо нее новую привязку), либо привязать к себе. Сначала я покажу вам первый вариант, а затем объясню, что я подразумеваю под привязкой к себе.

currentEmployee может быть преобразован в пару getter/setter и реализован следующим образом (только с отображением setter):

public function set currentEmployee( employee : Employee ) : void {
    if ( _currentEmployee != employee ) {
        if ( _currentEmployee != null ) {
            currentEmployeeNameCW.unwatch();
        }

        _currentEmployee = employee;

        if ( _currentEmployee != null ) {
            currentEmployeeNameCW = BindingUtils.bindSetter(currentEmployeeNameChanged, _currentEmployee, "name");
        }
    }
}

Когда свойство currentEmployee установлено, оно проверяет, было ли Предыдущее значение, и если это так, то удаляет привязку для этого объекта ( currentEmployeeNameCW.unwatch()), затем устанавливает закрытую переменную, а если новое значение не было null , то устанавливает новую привязку для свойства name . Самое главное, что он сохраняет ChangeWatcher , возвращенный вызовом привязки.

Это основной шаблон привязки, и я думаю, что он отлично работает. Однако есть один трюк, который можно использовать, чтобы сделать его немного проще. Вместо этого вы можете привязаться к себе. Вместо того чтобы настраивать и удалять привязки каждый раз, когда изменяется свойство currentEmployee , вы можете попросить систему привязки сделать это за вас. В вашем обработчике creationComplete (или конструкторе, или, по крайней мере, на некоторое время раньше) вы можете настроить привязку следующим образом:

BindingUtils.bindSetter(currentEmployeeNameChanged, this, ["currentEmployee", "name"]);

При этом устанавливается привязка не только к свойству currentEmployee на this , но и к свойству name на этом объекте. Так что в любое время, когда либо изменится метод currentEmployeeNameChanged будет вызван. Нет необходимости сохранять ChangeWatcher , потому что привязка никогда не будет удалена.

Второе решение работает во многих случаях, но я обнаружил, что первое иногда необходимо, особенно при работе с привязками в классах без представления (так как this должен быть диспетчером событий, а currentEmployee должен быть привязываемым для его работы).


  Сведения об ответе

VCe znayu

22:12, 4th August, 2020

Она существует и по сей день. :)

Я только что выпустил свой проект привязки данных ActionScript с открытым исходным кодом: http://code.google.com/p/bindage-tools

BindageTools-это альтернатива BindingUtils (смотрите игру слов там?), который использует fluent API, где вы объявляете привязки данных в стиле конвейера:

Bind.fromProperty(person, "firstName")
    .toProperty(firstNameInput, "text");

Двухсторонние привязки:

Bind.twoWay(
    Bind.fromProperty(person, "firstName"),
    Bind.fromProperty(firstNameInput, "text"));

Явное преобразование и проверка данных:

Bind.twoWay(
    Bind.fromProperty(person, "age")
        .convert(valueToString()),
    Bind.fromProperty(ageInput, "text")
        .validate(isNumeric()) // (Hamcrest-as3 matcher)
        .convert(toNumber()));

И т.д. На сайте есть еще много примеров. Есть много других функций тоже-приходите посмотреть. --Мэтью

Редактировать: обновлен APIs


  Сведения об ответе

ITSME

23:16, 14th August, 2020

Один из способов разделить MXML и ActionScript для компонента на отдельные файлы - это сделать что-то похожее на код ASP.Net 1.x, лежащий в основе модели. В этой модели декларативная часть (в данном случае MXML) является подклассом императивной части (ActionScript). Поэтому я мог бы объявить код для такого класса, как этот:

package CustomComponents
{
    import mx.containers.*;
    import mx.controls.*;
    import flash.events.Event;

    public class MyCanvasCode extends Canvas
    {
        public var myLabel : Label;

        protected function onInitialize(event : Event):void
        {
            MyLabel.text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.";
        }
    }
}
...

и markup вот так:

<?xml version="1.0" encoding="utf-8"?>
<MyCanvasCode xmlns="CustomComponents.*" 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    initialize="onInitialize(event)">
    <mx:Label id="myLabel"/>    
</MyCanvasCode>

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


  Сведения об ответе

KOMP

05:44, 5th August, 2020

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

С уважением,

Рут


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться