Предупреждение Flex: невозможно привязать свойство 'foo' к классу 'Object' (класс не является IEventDispatcher) - PullRequest
23 голосов
/ 30 мая 2009

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

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

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. Что этот ответ не говорит мне, это особенности реализации этого интерфейса (что требуется? Что нет?), И если есть более простой способ сделать это - например, встроенный класс, который с радостью примет мои пользовательские свойства и позволит для связывания, без необходимости беспокоиться о деталях реализации интерфейса.

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

Ответы [ 7 ]

15 голосов
/ 30 мая 2009

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

<?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>
8 голосов
/ 30 мая 2009

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

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

[Bindable] public var currentLink:ObjectProxy = new ObjectProxy(emptyLink);
4 голосов
/ 30 мая 2009

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

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

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

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

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

3 голосов
/ 19 ноября 2013

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

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

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

2 голосов
/ 29 июля 2010

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

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

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

или

public function get foo() : FooObject {
...
}
1 голос
/ 30 мая 2009

Вот ссылка на liveocs для интерфейса. В значительной степени это было бы очевидно.

Цитировать:

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

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

приватная статическая константа emptyLink: EventDispatcher = {

0 голосов
/ 30 мая 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}" />

Что-то вроде этого, возможно?

...