Flex 警告:无法绑定到属性“foo” 在“对象”类上 (类不是 IEventDispatcher)

发布于 2024-07-22 06:26:12 字数 1894 浏览 6 评论 0原文

我有一个对象,其中包含十几个要绑定到表单元素的字段,以便我可以使用该对象将数据发送回服务器进行保存。

我的容器对象的定义:

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) 警告:无法绑定到类“Object”上的属性“trigger5”(类不是 IEventDispatcher)

并且当 TextInput 字段更改时,currentLink 对象不会更新。

显而易见的答案是我的对象需要是实现 IEventDispatcher 的类的实例。 这个答案没有告诉我的是实现该接口的细节(需要什么?不需要什么?),以及是否有一种更简单的方法来做到这一点——比如一个内置的类,它将很乐意接受我的自定义属性并允许对于绑定,我不必担心实现接口的细节。

存在这样的类吗? 如果不是,完成这项任务的最低限度和/或可接受的标准是什么?

I've got an object that contains a dozen or so fields I want to bind to form elements, so that I can use that object to send the data back to the server to be saved.

Definition of my container object:

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 is assigned at runtime to a specific index from an ArrayCollection, I'm just using the emptyLink object for initialization purposes, mostly.

<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>

Of course, this compiles and displays just fine, but there are runtime warnings for each instance:

warning: unable to bind to property 'trigger1' on class 'Object' (class is not an IEventDispatcher)
warning: unable to bind to property 'trigger2' on class 'Object' (class is not an IEventDispatcher)
warning: unable to bind to property 'trigger3' on class 'Object' (class is not an IEventDispatcher)
warning: unable to bind to property 'trigger4' on class 'Object' (class is not an IEventDispatcher)
warning: unable to bind to property 'trigger5' on class 'Object' (class is not an IEventDispatcher)

And the currentLink object is not updated when the TextInput fields are changed.

The obvious answer is that my object needs to be an instance of a class that implements IEventDispatcher. What that answer doesn't tell me is the particulars of implementing that interface (what's required? what's not?), and if there is a simpler way to do this -- like a built in class that will gladly accept my custom properties and allow for binding, without me having to worry about the particulars of implementing the interface.

Does such a class exist? If not, what's the bare minimum and/or accepted standard for accomplishing this task?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

早茶月光 2024-07-29 06:26:12

您需要使用 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>

You need to use ObjectProxy (as Chetan mentions) - but you also need to use valueCommit to get the text you enter in the input BACK into your object:

<?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>
伤感在游骋 2024-07-29 06:26:12

Object 不调度事件。 尽管您已将变量设置为可绑定,但无法绑定变量 currentLink 引用的对象的属性。

请改用ObjectProxy

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

Object doesn't dispatch events. Although you have made the variable Bindable, the properties of the object referenced by the variable currentLink can not be bound.

Use ObjectProxy instead.

[Bindable] public var currentLink:ObjectProxy = new ObjectProxy(emptyLink);
独自唱情﹋歌 2024-07-29 06:26:12

您需要了解的第一件事是 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 的类,因此支持绑定。 这样做的优点是比原型对象更快,并且还可以进行编译时检查,即如果引用无效属性,您将收到编译器错误。

另一种选择是按照其他 SO 成员之一的建议将原型包装在 ObjectProxy 中。

The first thing you'll want to know is that binding in Flex 3 is not bidirectional. The binding expression will ensure that if the source of the binding expression (currentLink.trigger1) changes that the target (TextInput) will receive notification of the change and update accordingly. If you want the binding to go in the other direction, there are at least two ways to do this:

  1. Use the mx:Binding tag to direct TextInput.text back to the object
  2. Use BindingUtils to do this programmatically instead.

In Flex 4 they are introducing a new syntax for bidirectional binding @{some.binding.expression} but it's not available in Flex 3.

On the 2nd part: the error that you're receiving is because you are binding to a "generic" prototype Object. When you apply the [Bindable] metadata tag to a property or class, the MXMLC compiler generates AS code that includes use of binding utilities and property change watchers to do make the binding happen. However you can't make the prototype Object do this since it's a built-in. You can create a custom ActionScript class which is bindable (or has certain properties bindable). The MXMLC compiler will generate a class which implements IEventDispatcher and therefore supports binding. This has the advantage of being faster than prototype objects and also gives you compile-time checking, i.e. you will receive a compiler error if you reference an invalid property.

The other alternative is to wrap your prototype in ObjectProxy as one of the other SO members has suggested.

痴意少年 2024-07-29 06:26:12

关于如何在较大项目中找出有问题的代码的提示 -

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

在 SDK 的 PropertyWatcher 类中的两行上放置一个断点(Navigate > Open Type > ...)。 然后 Stacktrace 将帮助您找到保存损坏绑定的 ui 组件。

Just a tip on how to find out the offending code in a larger project - put a breakpoint on the two

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

lines in the SDK's PropertyWatcher class (Navigate > Open Type > ...). Stacktrace will then help you find the ui component that holds the broken binding.

少年亿悲伤 2024-07-29 06:26:12

一般来说,您得到“无法绑定到类上的属性 foo 的原因是因为您缺少 foo 的 getter 或 setter。您也可以 foo 的作用域为公共变量,(尽管这破坏了封装)

所以你需要这两个来让它消失:

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

或者

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

In general, the reason why you get "unable to bind to property foo on a class, is because you are either missing a getter or setter for foo. You could also make foo scoped to a public variable, (although this breaks encapsulation)

So you need Both of these to make it go away:

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

or

public function get foo() : FooObject {
...
}
过期情话 2024-07-29 06:26:12

这是该界面的 livedocs 参考。 这几乎是显而易见的。

去引用:

一般来说,用户定义的类获得事件调度功能的最简单方法是扩展EventDispatcher。

因此,

私有静态常量emptyLink:EventDispatcher = {

Here's the livedocs reference for the interface. It's pretty much what would be obvious.

To quote:

In general, the easiest way for a user-defined class to gain event dispatching capabilities is to extend EventDispatcher.

Hence,

private static const emptyLink:EventDispatcher = {

梦明 2024-07-29 06:26:12

我使用 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}" />

也许是这样的东西?

I haven't been using Flex for very long, and this might not fit your requirements, but why not use XML? I believe you can set the TextInput text value to attributes in the XML.

I'm using pseudo-code, but something like this makes sense to me:

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

Something like this, perhaps?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文