Trying to use BindingUtils in Flash AS3.0

穿精又带淫゛_ 提交于 2019-12-22 19:43:25

问题


I am not able to make this code work in AS3.0 ( Flash ) with Flex SDK 4.0 included.

 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());
 }

The output i get is :

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

and so on.

But I expect the correct output should be :

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

Thanks.


回答1:


I'm not exactly sure how the Flash Pro compiler treats this stuff (I always use the free mxmlc compiler from the Flex SDK).

Does this work for you?

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

If not, try this for the Model definition:

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"));
    }
  }
}

If that doesn't work, try this for the Model:

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));
    }
  }
}

Or, perhaps with an 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);
    }
  }
}

All of the above work fine when compiling with mxmlc. I'd avoid the ObjectProxy as it's the least typesafe.




回答2:


Data binding only works with 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>



回答3:


You wrote:

I am not able to make this code work in AS3.0 ( Flash ) with Flex SDK 4.0 included.

I take it this means you are already using the mxmlc compiler, which is necessary for the Bindable metatag to work.

As I understand it, adding the Bindable meta tag to a variable is a way to listen for dispatches of a PropertyChangeEvent:

The Flex 4.6 API docs state:

[When using Bindable on a variable] The Flex compiler automatically generates an event named propertyChange, of type PropertyChangeEvent, for the property.

Basically a simpler way to do myValue.addEventListener(...)

So the variable we want to be Bindable must be of a type that extends EventDispatcher or implements IEventDispatcher. This is not the case with the primitive int which is the type of the variable you are trying to make bindable. Bindable on an int will not work.

To make it work you could wrap the int variable in a custom class BindableInteger that implements IEventDispatcher. Another options is to use ObjectProxy, which allows you to add EventListeners and make an object bindable even though it doesn't extend EventDispatcher or implements IEventDispatcher.

Also, note that you need to make your variable public, protected or private for Bindable to work.

Flex 4.6 docs on Using the Bindable meta tag:

You can use the [Bindable] metadata tag (...) [b]efore a public, protected, or private property defined as a variable to make that specific property support binding.

This will not work:

[Bindable] var myValue:int = 0;

but this will:

[Bindable] public var myValue:int = o;



回答4:


Binding works for class properties, and doesn't work with local variables so you need to create the class:

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());
    }
}
}


来源:https://stackoverflow.com/questions/13904382/trying-to-use-bindingutils-in-flash-as3-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!