Предупреждение Flex: невозможно выполнить привязку к свойству 'foo' в классе 'Object' (класс не является IEventDispatcher)

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

Определение моего объекта-контейнера:

private static const emptyLink:Object = {
    id: -1, title:'',
    trigger1:'',trigger2:'',trigger3:'',trigger4:'',trigger5:'',
    linkTitle:'', linkBody:'',
    answer1:'',answer2:'',answer3:'',answer4:'',answer5:''
};

[Bindable] public var currentLink:Object = emptyLink;

currentLink назначается во время выполнения конкретному индексу из ArrayCollection, я просто использую объект emptyLink в основном для целей инициализации.

<mx:Panel id="triggerPanel" title="Trigger" width="33%">
    <mx:VBox id="tpBoxes" width="100%" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5">
        <mx:TextInput id="trigger1" width="100%" textAlign="left" text="{currentLink.trigger1}" />
        <mx:TextInput id="trigger2" width="100%" textAlign="left" text="{currentLink.trigger2}" />
        <mx:TextInput id="trigger3" width="100%" textAlign="left" text="{currentLink.trigger3}" />
        <mx:TextInput id="trigger4" width="100%" textAlign="left" text="{currentLink.trigger4}" />
        <mx:TextInput id="trigger5" width="100%" textAlign="left" text="{currentLink.trigger5}" />
    </mx:VBox>
</mx:Panel>

Конечно, это компилируется и отображается нормально, но для каждого экземпляра есть предупреждения во время выполнения:

предупреждение: невозможно привязать к свойству 'trigger1' в классе 'Object' (класс не является IEventDispatcher) предупреждение: невозможно привязать к свойству 'trigger2' в классе 'Object' (класс не является IEventDispatcher) предупреждение: невозможно привязать к свойство «trigger3» в классе «Object» (класс не является IEventDispatcher) предупреждение: невозможно привязать к свойству «trigger4» в классе «Object» (класс не является IEventDispatcher) предупреждение: невозможно привязать к свойству «trigger5» в классе 'Object' (класс не является IEventDispatcher)

И объект currentLink не обновляется при изменении полей TextInput.

Очевидный ответ: мой объект должен быть экземпляром класса, реализующего IEventDispatcher. О чем мне не говорит этот ответ, так это об особенностях реализации этого интерфейса (что требуется? Что нет?), И если есть более простой способ сделать это - например, встроенный класс, который с радостью примет мои настраиваемые свойства и разрешит для привязки, и мне не нужно беспокоиться о деталях реализации интерфейса.

Такой класс существует? Если нет, то каков минимальный и / или принятый стандарт для выполнения этой задачи?


person Adam Tuttle    schedule 29.05.2009    source источник


Ответы (7)


Вам нужно использовать ObjectProxy (как упоминает Четан), но вам также нужно использовать valueCommit, чтобы получить текст, который вы вводите во вводе, НАЗАД в свой объект:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    <mx:Script>
        <![CDATA[
            import mx.utils.ObjectProxy;
              private static const emptyLink:Object = {
    id: -1, title:'',
    trigger1:'',trigger2:'',trigger3:'',trigger4:'',trigger5:'',
    linkTitle:'', linkBody:'',
    answer1:'',answer2:'',answer3:'',answer4:'',answer5:''
};

[Bindable] public var currentLink:ObjectProxy = new ObjectProxy(emptyLink);


private function handleClick():void
{
    trace(currentLink.trigger1);
}
]]>
</mx:Script>

<mx:Panel id="triggerPanel" title="Trigger" width="33%">
        <mx:VBox id="tpBoxes" width="100%" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5">
                <mx:TextInput  id="trigger1" width="100%" textAlign="left" text="{currentLink.trigger1}" valueCommit="{currentLink.trigger1 = trigger1.text;}"/>

                <mx:Button label="Click" click="handleClick()"/>
        </mx:VBox>
</mx:Panel>        

</mx:WindowedApplication>
person Gabriel    schedule 29.05.2009

Object не отправляет события. Хотя вы сделали переменную привязанной, свойства объекта, на который ссылается переменная currentLink, не могут быть привязаны.

Вместо этого используйте ObjectProxy.

[Bindable] public var currentLink:ObjectProxy = new ObjectProxy(emptyLink);
person Chetan S    schedule 29.05.2009

Первое, что вам нужно знать, это то, что привязка в Flex 3 не является двунаправленной. Выражение привязки гарантирует, что если источник выражения привязки (currentLink.trigger1) изменится, цель (TextInput) получит уведомление об изменении и обновит его соответствующим образом. Если вы хотите, чтобы привязка шла в другом направлении, есть как минимум два способа сделать это:

  1. Используйте тег mx: Binding, чтобы направить TextInput.text обратно к объекту
  2. Вместо этого используйте BindingUtils, чтобы сделать это программно.

Во Flex 4 они вводят новый синтаксис для двунаправленной привязки @ {some.binding.expression}, но он недоступен во Flex 3.

Во второй части: ошибка, которую вы получаете, связана с привязкой к «общему» объекту-прототипу. Когда вы применяете тег метаданных [Bindable] к свойству или классу, компилятор MXMLC генерирует код AS, который включает в себя использование утилит привязки и наблюдателей за изменениями свойств для выполнения привязки. Однако вы не можете заставить объект-прототип делать это, поскольку он является встроенным. Вы можете создать собственный класс ActionScript, который может быть привязан (или имеет определенные свойства, которые можно привязывать). Компилятор MXMLC сгенерирует класс, который реализует IEventDispatcher и, следовательно, поддерживает привязку. Это имеет то преимущество, что работает быстрее, чем объекты-прототип, а также дает вам возможность проверки во время компиляции, то есть вы получите ошибку компилятора, если вы укажете недопустимое свойство.

Другая альтернатива - обернуть ваш прототип в ObjectProxy, как предложил один из других участников SO.

person cliff.meyers    schedule 29.05.2009
comment
Если бы я мог принять 2 ответа, это был бы №2. Я выбрал «Габриэль», потому что это было простейшее решение того, что я пытаюсь сделать. Тем не менее, спасибо за всю информацию! - person Adam Tuttle; 01.06.2009

Просто подсказка о том, как найти проблемный код в большом проекте - поставьте точку останова на двух

trace("warning: unable to bind to property '"

строки в классе SDK PropertyWatcher («Навигация»> «Открыть тип»> ...). Затем Stacktrace поможет вам найти компонент пользовательского интерфейса, содержащий разорванную привязку.

person Stepan    schedule 19.11.2013

В общем, причина, по которой вы получаете "невозможно привязать к свойству foo в классе, заключается в том, что вам не хватает геттера или сеттера для foo. Вы можете также сделать foo привязан к общедоступной переменной (хотя это нарушает инкапсуляцию)

Итак, вам нужны оба из них, чтобы он исчез:

public function set foo (o:FooObject) : void {
...
}

or

public function get foo() : FooObject {
...
}
person willedw    schedule 29.07.2010

Вот справочник Liveocs по интерфейсу. Это в значительной степени то, что было бы очевидно.

Цитировать:

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

Следовательно,

private static const emptyLink: EventDispatcher = {

person dkretz    schedule 29.05.2009
comment
ваша ссылка не ведет на страницу в liveocs, как вы думали. Каждая справочная страница Liveocs имеет текущую ссылку: ... в нижнем колонтитуле с URL-адресом для прямой ссылки на страницу, которую вы просматриваете. Используйте это. :) - person Adam Tuttle; 02.06.2009

Я не очень давно использую Flex, и это может не соответствовать вашим требованиям, но почему бы не использовать XML? Я считаю, что вы можете установить текстовое значение TextInput для атрибутов в XML.

Я использую псевдокод, но для меня это имеет смысл:

[Bindable] private static const currentLink:XML = <root>
                                                    <trigger1 value=""/>
                                                    <trigger2 value="" />
                                                  </root>;
...
<mx:TextInput id="trigger1" width ... text="{currentLink.trigger1.@value}" />

Что-то вроде этого, может быть?

person bedwyr    schedule 29.05.2009