【问题标题】:Trying to use BindingUtils in Flash AS3.0尝试在 Flash AS3.0 中使用 BindingUtils
【发布时间】:2012-12-16 18:44:29
【问题描述】:

我无法使此代码在包含 Flex SDK 4.0 的 AS3.0 (Flash) 中运行。

 import mx.binding.utils.*;


 [Bindable]
 var myValue:int = 0;
 var cw:ChangeWatcher = BindingUtils.bindSetter(myValueChanged, this, "myValue");
 addEventListener( Event.ENTER_FRAME , ef);

 function ef(e:Event):void
 {
    trace("hello",getTimer());
    myValue = getTimer();
 }

 function myValueChanged(o:Object):void
 {
    trace("myValue: " + myValue.toString());
 }

我得到的输出是:

myValue: 0
hello 157
hello 168
hello 171
hello 177
....
....

等等。

但我希望正确的输出应该是:

myValue: 0
hello 157
myValue: 157
hello 168
myValue: 168
hello 171
myValue: 171
hello 177
myValue: 177
....
....

谢谢。

【问题讨论】:

    标签: actionscript-3 apache-flex flex4


    【解决方案1】:

    数据绑定仅适用于 Flex。

    <?xml version="1.0" encoding="utf-8"?>
    <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                           xmlns:s="library://ns.adobe.com/flex/spark"
                           xmlns:mx="library://ns.adobe.com/flex/mx" enterFrame="ef(event)">
    
        <fx:Declarations>
            <!-- Place non-visual elements (e.g., services, value objects) here -->
        </fx:Declarations>
        <fx:Script>
            <![CDATA[
                import mx.binding.utils.*;
    
                [Bindable]
                public var myValue:int = 0;
                private var cw:ChangeWatcher = BindingUtils.bindSetter(myValueChanged, this, "myValue");
    
                private function ef(e:Event):void
                {
                    trace("hello", getTimer());
                    myValue = getTimer();
                }
    
                private function myValueChanged(o:Object):void
                {
                    trace("myValue: " + myValue.toString());
                }
            ]]>
        </fx:Script>
    </s:WindowedApplication>
    

    【讨论】:

    • 我没有看到背后的逻辑,为什么它不能在 Flash 中工作,如果我使用相同的 Flex SDK(这使得它在 Flex 中成为可能)
    • 绑定只是动作脚本——但它是由 flex 编译器添加的(与 flash pro 中的编译器不同)。您需要使用 mxmlc 进行编译(请参阅 help.adobe.com/en_US/flex/using/…)以利用 [Bindable]
    • 斯卡比尔是对的。当您使用 [Bindable] 元数据时,mxml 编译器会为可绑定的属性生成一个 getter/setter。 setter 方法在属性更改时调度事件。如果您自己也这样做,您可以使用 BindingUtils 来完成这项工作。
    • 抱歉,我的意思是说@Lee Burrows 是对的。如果您自己调度事件,绑定将起作用。 Flex 编译器 (mxmlc) 会将 [Bindable] 元数据转换为 Actionscript 代码,而 Flash Pro 编译器会忽略它。
    【解决方案2】:

    我不确定 Flash Pro 编译器如何处理这些东西(我总是使用 Flex SDK 中的免费 mxmlc 编译器)。

    这对你有用吗?

    package
    {
      import flash.display.Sprite;
      import flash.events.Event;
      import flash.utils.getTimer;
      import mx.binding.utils.BindingUtils;
    
      public class BindingExample extends Sprite {
    
        private var model:Model;
    
        public function BindingExample()
        {
          model = new Model();
          BindingUtils.bindProperty(this, 'spy', model, ['value']);
          addEventListener( Event.ENTER_FRAME , onEnterFrame);
        }
    
        public function onEnterFrame(e:Event):void
        {
          model.value = getTimer();
        }
    
        public function set spy(value:int):void
        {
          trace('Bound property set to: ' + value);
        }
      }
    }
    
    class Model
    {
      [Bindable]
      public var value:int;
    }
    

    如果没有,试试这个模型定义:

    import flash.events.Event;
    import flash.events.EventDispatcher;
    
    class Model extends EventDispatcher
    {
      private var _value:int;
    
      [Bindable("valueChange")]
      public function get value():int
      {
        return _value;
      }
    
      public function set value(value:int):void
      {
        if (_value != value)
        {
          trace('Model property set to: ' + value);
          _value = value;
          dispatchEvent(new Event("valueChange"));
        }
      }
    }
    

    如果这不起作用,请为模型尝试这个:

    import flash.events.EventDispatcher;
    import mx.events.PropertyChangeEvent;
    import mx.events.PropertyChangeEventKind;
    
    class Model extends EventDispatcher
    {
      private var _value:int;
    
      [Bindable("propertyChange")]
      public function get value():int
      {
        return _value;
      }
    
      public function set value(value:int):void
      {
        if (_value != value)
        {
          trace('Model property set to: ' + value);
          var oldValue:int = _value;
          _value = value;
          dispatchEvent(new PropertyChangeEvent(
            PropertyChangeEvent.PROPERTY_CHANGE, false, false,
            PropertyChangeEventKind.UPDATE, "value", oldValue, value, this));
        }
      }
    }
    

    或者,也许使用 ObjectProxy:

    package
    {
      import flash.display.Sprite;
      import flash.events.Event;
      import flash.utils.getTimer;
      import mx.binding.utils.BindingUtils;
      import mx.utils.ObjectProxy;
    
      public class BindingExample extends Sprite {
    
        private var model:ObjectProxy;
    
        public function BindingExample()
        {
          model = new ObjectProxy({value: 0});
          BindingUtils.bindProperty(this, 'spy', model, ['value']);
          addEventListener( Event.ENTER_FRAME , onEnterFrame);
        }
    
        public function onEnterFrame(e:Event):void
        {
          model.value = getTimer();
        }
    
        public function set spy(value:int):void
        {
          trace('Bound property set to: ' + value);
        }
      }
    }
    

    使用 mxmlc 编译时,上述所有操作都可以正常工作。我会避免使用 ObjectProxy,因为它是最不安全的。

    【讨论】:

    • 非常感谢!除了第一个代码块,第二个、第三个和第四个代码块的组合就像微风一样! :)
    【解决方案3】:

    你写道:

    我无法使此代码在包含 Flex SDK 4.0 的 AS3.0 (Flash) 中运行。

    我认为这意味着您已经在使用 mxmlc 编译器,这是 Bindable 元标记工作所必需的。

    据我了解,将 Bindable 元标记添加到变量是一种侦听 PropertyChangeEvent 调度的方法:

    Flex 4.6 API docs 状态:

    [在变量上使用 Bindable 时] Flex 编译器会自动为属性生成一个名为 propertyChange、类型为 PropertyChangeEvent 的事件。

    基本上是一个更简单的方法来做myValue.addEventListener(...)

    所以我们想要绑定的变量必须是扩展EventDispatcher或实现IEventDispatcher的类型。原始 int 不是这种情况,它是您尝试使其可绑定的变量的类型。 Bindable int 将不起作用。

    要使其工作,您可以将int 变量包装在实现IEventDispatcher 的自定义类BindableInteger 中。另一种选择是使用ObjectProxy,它允许您添加事件监听器并使对象可绑定,即使它没有扩展EventDispatcher 或实现IEventDispatcher

    另外,请注意,您需要将变量设为公开、受保护或私有,才能使 Bindable 正常工作。

    Using the Bindable meta tag 上的 Flex 4.6 文档:

    您可以在定义为变量的公共、受保护或私有属性之前使用 [Bindable] 元数据标记 (...) [b],以使该特定属性支持绑定。

    这不起作用:

    [Bindable] var myValue:int = 0;
    

    但这会:

    [Bindable] public var myValue:int = o;
    

    【讨论】:

    • 是的,我也试过了(使用了在这个帖子中回复的用户“fsbmain”的代码)。但还是不行。
    • hmm...实际上一个成员也向我建议了这个:help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/… 这与您更新的答案有些相似,但内置了。
    • 我已经更新了我的答案,提到了 ObjectProxy。包装你自己的类型和使用 ObjectProxy 都可以。
    • 感谢 Gunnar 的更新。您说 =>“我认为这意味着您已经在使用 mxmlc 编译器,这是 Bindable 元标记工作所必需的。”。不,我仅将 sdk 用于 mx 包。最终使用的是 Flash pro 编译器。但无论如何,这是一次学习经历,通过你的投入。 :)
    【解决方案4】:

    绑定适用于类属性,不适用于局部变量,因此您需要创建类:

    package
    {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.utils.getTimer;
    
    import mx.binding.utils.BindingUtils;
    import mx.binding.utils.ChangeWatcher;
    
    public class astest extends Sprite
    {
    
        [Bindable]
        public var myValue:int = 0;
    
        public function astest()
        {
            var cw:ChangeWatcher = BindingUtils.bindSetter(myValueChanged, this, "myValue");
            addEventListener( Event.ENTER_FRAME , ef);
        }
    
        protected function ef(e:Event):void
        {
            trace("hello",getTimer());
            myValue = getTimer();
        }
    
        protected function myValueChanged(o:Object):void
        {
            trace("myValue: " + myValue.toString());
        }
    }
    }
    

    【讨论】:

    • 我也这样做了。但它不起作用。这是一个链接:stackoverflow.com/questions/4036377/…,它建议检查“swc”ON。这是激活 as3 元标记的已知错误。我也这样做了,但还是不行
    猜你喜欢
    • 2011-05-10
    • 1970-01-01
    • 1970-01-01
    • 2012-08-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多