Flex 3 - 通过事件传递参数的问题

时间:2010-08-03 08:58:14

标签: flex parameters events

我遇到了一个问题,我无法理解为什么它会像那样......

在for循环中,我将for索引作为事件参数传递。但是,eventHandler得到了错误的索引,但是正确的目标......

这是一些代码。 .as类方法:

public function set dataProvider(a:Array):void
{
    var x:int = 0;
    if(a != null && a.length > 0)
    {   
        labelsArray = (new ArrayCollection(a));
        trace("##############################################################");
        for(var i:int = 0; i<a.length; i++)
        {
            var btn:NavigationArrowButtonCtrl = new NavigationArrowButtonCtrl();
            var s:String = (new ArrayCollection(a)).getItemAt(i).toString();
            trace(i + '/' + s);

            btn.addEventListener(FlexEvent.CREATION_COMPLETE, function(e:FlexEvent):void{
                var lblIndex:int = i;
                btnAddLblHandler(e, lblIndex);
            });

            this.addChild(btn); 
            this.setChildIndex(btn, 0);
        }
        trace("##############################################################");
    }
}

private function btnAddLblHandler(e:FlexEvent, ind:int):void
{
    trace(labelsArray.length.toString() + '/' + ind.toString());
    if(ind < labelsArray.length)
    {
        trace('Handler ' + ind + '/' + String(labelsArray.getItemAt(ind)));
        (e.target as NavigationArrowButtonCtrl).lbl_body.text = String(labelsArray.getItemAt(ind));
    }
}

这是我得到的结果跟踪:

##############################################################
0/FINITION
1/> MOTORISATIONS
2/> EXTERIEUR
3/> INTERIEUR
4/> OPTIONS
5/> RESUME
##############################################################

6/6
6/6
6/6
6/6
6/6
6/6

不知何故,处理程序只获取for索引'i'的最后一个值,因为它应该在每个循环中获得'i'的当前值(0/1/2/3/4/5)。 。 知道什么是错的吗?

感谢您的帮助! =) 的问候,

BS_C3

2 个答案:

答案 0 :(得分:1)

创建按钮并调用var lblIndex:int = i;时,for循环将完成其执行,i的值将为a.length,此处为6。您可以生成5种不同的功能,也可以稍微重新设计。

function getListener(i:Number):Function {
     return function(e:FlexEvent):void{
         var lblIndex:int = i;
         btnAddLblHandler(e, lblIndex);
     };
}
btn.addEventListener(FlexEvent.CREATION_COMPLETE, getListener(i));

看起来你试图在创建NavigationArrowButtonCtrl项后设置标签;更简单的方法是在该类中声明一个[Bindable]变量并将其绑定到lbl_body.text字段。如果你以后不打算更新它,你也不需要真正使用绑定;您只需从creationComplete处理程序中的公共变量更新lbl_body.text

因此代码看起来像:

//in NavigationArrowButtonCtrl.mxml
public var textvar:String;

//inside the for loop:
btn.textvar = labelsArray.getItemAt(i).toString();
btn.addEventListener(FlexEvent.CREATION_COMPLETE, btnAddLblHandler)

//inside btnAddLblHandler(e:FlexEvent):void
btn.lbl_body.text = btn.textvar;

//you can do it from the NavigationArrowButtonCtrl class itself
this.lbl_body.text = this.textvar;

不要依赖e.target - 而是使用e.currentTarget。 target可以是按钮的某个子节点 - currentTarget将始终具有注册事件侦听器的对象。

顺便说一句,不要在循环的每次迭代中创建相同的数组:

取代:

var s:String = (new ArrayCollection(a)).getItemAt(i).toString();

var s:String = labelsArray.getItemAt(i).toString();

答案 1 :(得分:0)

这就是我为解决问题所做的工作(范围事项): - &gt;与以前相同的代码,只是将'for'部分封装在函数中。

public function set dataProvider(a:Array):void
{
    var x:int = 0;
    if(a != null && a.length > 0)
    {   
        labelsArray = (new ArrayCollection(a));
        trace("##############################################################");
        for(var i:int = 0; i<a.length; i++)
        {
            createBtn(i, a);
        }
        trace("##############################################################");
    }
}

private function createBtn(i:int, a:Array):void
{
    var btn:NavigationArrowButtonCtrl = new NavigationArrowButtonCtrl();
    var s:String = (new ArrayCollection(a)).getItemAt(i).toString();
    trace(i + '/' + s);

    btn.addEventListener(FlexEvent.CREATION_COMPLETE, function(e:FlexEvent):void{
            var lbl:String = s;
            btnAddLblHandler(e, lbl);
        }); 

    this.addChild(btn); 
}

private function btnAddLblHandler(e:FlexEvent, ind:int):void
{
    trace(labelsArray.length.toString() + '/' + ind.toString());
    if(ind < labelsArray.length)
    {
        trace('Handler ' + ind + '/' + String(labelsArray.getItemAt(ind)));
        (e.target as NavigationArrowButtonCtrl).lbl_body.text = String(labelsArray.getItemAt(ind));
    }
}