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

StackOverflow https://stackoverflow.com/questions/928081

Вопрос

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

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

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

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

Это было полезно?

Решение

Вам нужно использовать 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>

Другие советы

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

Использование ObjectProxy вместо этого.

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

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

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

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

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

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

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

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

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

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

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

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

или

public function get foo() : FooObject {
...
}

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

Процитировать:

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

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

частная статическая постоянная пустая ссылка:EventDispatcher = {

Я не очень давно использую 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}" />

Может быть, что-то вроде этого?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top