web-dev-qa-db-ja.com

Flex警告:クラス 'Object'のプロパティ 'foo'にバインドできません(クラスはIEventDispatcherではありません)

フォーム要素にバインドしたいフィールドが12個ほど含まれているオブジェクトがあるので、そのオブジェクトを使用してデータをサーバーに送り返して保存することができます。

私のコンテナオブジェクトの定義:

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>

もちろん、これは正常にコンパイルおよび表示されますが、インスタンスごとに実行時の警告があります。

警告:クラス 'Object'のプロパティ 'trigger1'にバインドできません(クラスはIEventDispatcherではありません)警告:クラス 'Object'のプロパティ 'trigger2'にバインドできません(クラスはIEventDispatcherではありません)警告:バインドできませんクラス 'Object'のプロパティ 'trigger3'(クラスはIEventDispatcherではありません)警告:クラス 'Object'のプロパティ 'trigger4'にバインドできません(クラスはIEventDispatcherではありません)警告:クラスのプロパティ 'trigger5'にバインドできません'オブジェクト'(クラスはIEventDispatcherではありません)

また、currentLinkフィールドが変更されても、TextInputオブジェクトは更新されません。

明白な答えは、私のオブジェクトはIEventDispatcherを実装するクラスのインスタンスである必要があるということです。その答えが私に教えてくれないのは、そのインターフェースを実装することの詳細(何が必要ですか?何が必要ではないのですか?)、そしてこれを行うためのより簡単な方法があるかどうかです-私のカスタムプロパティを喜んで受け入れて許可する組み込みクラスのようにバインディングのために、インターフェースの実装の詳細について心配する必要はありません。

そのようなクラスは存在しますか?そうでない場合、このタスクを達成するための最低限および/または受け入れられている基準は何ですか?

24
Adam Tuttle

ObjectProxyを使用する必要があります(Chetanが言及しているように)-しかし、入力に入力したテキストをオブジェクトに戻すには、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>
16
Gabriel

Objectはイベントをディスパッチしません。変数をバインド可能にしましたが、変数currentLinkによって参照されるオブジェクトのプロパティをバインドすることはできません。

代わりにObjectProxyを使用してください。

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

最初に知りたいのは、Flex3でのバインドは双方向ではないということです。バインディング式は、バインディング式のソース(currentLink.trigger1)が変更された場合に、ターゲット(TextInput)が変更の通知を受け取り、それに応じて更新されることを保証します。バインディングを他の方向に移動させたい場合、これを行うには少なくとも2つの方法があります。

  1. Mx:Bindingタグを使用して、TextInput.textをオブジェクトに戻します
  2. 代わりに、BindingUtilsを使用してこれをプログラムで実行します。

Flex 4では、双方向バインディング@ {some.binding.expression}の新しい構文が導入されていますが、Flex3では使用できません。

2番目の部分:あなたが受け取っているエラーは、あなたが「一般的な」プロトタイプオブジェクトにバインドしているためです。 [Bindable]メタデータタグをプロパティまたはクラスに適用すると、MXMLCコンパイラは、バインディングユーティリティとプロパティ変更ウォッチャーを使用してバインディングを実行することを含むASコードを生成します。ただし、プロトタイプオブジェクトは組み込みであるため、これを実行させることはできません。バインド可能な(またはバインド可能な特定のプロパティを持つ)カスタムActionScriptクラスを作成できます。 MXMLCコンパイラは、IEventDispatcherを実装するため、バインディングをサポートするクラスを生成します。これには、プロトタイプオブジェクトよりも高速であるという利点があり、コンパイル時のチェックも可能です。つまり、無効なプロパティを参照すると、コンパイラエラーが発生します。

他の選択肢は、他のSOメンバーが提案したように、プロトタイプをObjectProxyでラップすることです。

5
cliff.meyers

大規模なプロジェクトで問題のあるコードを見つける方法のヒント-2つにブレークポイントを設定します

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

sDKのPropertyWatcherクラスの行([ナビゲート]> [オープンタイプ]> ...)。 Stacktraceは、壊れたバインディングを保持しているuiコンポーネントを見つけるのに役立ちます。

3
Stepan

一般に、「クラスのプロパティfooにバインドできないのは、fooのゲッターまたはセッターがない。あなたができたからです。 fooのスコープをパブリック変数にします(ただし、これはカプセル化を破ります)

したがって、それをなくすには、これらの両方が必要です。

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

または

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

これがlivedocsリファレンスです インターフェース用。それはほとんど明白なことです。

引用するには:

一般に、ユーザー定義クラスがイベントディスパッチ機能を取得する最も簡単な方法は、EventDispatcherを拡張することです。

したがって、

private static const emptyLink:EventDispatcher = {

1
dkretz

私は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}" />

たぶん、このようなもの?

0
bedwyr