Flex 3: удаление элементов из коллекции массивов, когда пользователь нажимает кнопку, и отражение этого в повторителе

У меня есть arrayCollection со следующей структурой:

projectErrorsAC
    0
        project1number
        project2number
        position1number
        position2number
        project1name
        project2name
        student
    1
        ...

AC определяется следующим образом:

[Bindable] private var projectErrorsAC:ArrayCollection = new ArrayCollection;

Я использую этот AC в повторителе для отображения каждой ошибки. После отображения каждой ошибки я разместил кнопку «Принять» и «Отклонить». Как только пользователь нажимает любую из этих кнопок, я хочу вызвать функцию, которая удаляет конкретную ошибку из AC. Вот что у меня есть до сих пор:

Повторитель:

<mx:Repeater id="projRP" width="100%" dataProvider="{projectErrorsAC}">
<mx:HBox>
    <mx:Text id="projmsg" text="{projRP.currentItem.student} is working on the following projects on the same day: {projRP.currentItem.proj1name} and {projRP.currentItem.proj2name}." />
    <mx:Text id="allow" text="Allow" color="#ff0000" selectable="false" 
        click="acceptProjConflict(projRP.currentItem);" 
        mouseOver="parentApplication.switchCursor(true);" 
        mouseOut="parentApplication.switchCursor(false);" />
    <mx:Text text=" |" />
    <mx:Text id="decline" text="Decline" color="#ff0000" selectable="false" click="declineProjConflict(projRP.currentItem);" mouseOver="parentApplication.switchCursor(true);" mouseOut="parentApplication.switchCursor(false);" />
</mx:HBox>
</mx:Repeater>

и вот функция, которую я вызываю в части «щелчок»:

public function acceptProjConflict(conflict:Object):void
{
for (var i:int = 0; i < projectErrorsAC.length; i++)
{
    if (projectErrorsAC.getItemAt(i) == conflict)
        projectErrorsAC.removeItemAt(i);
}               
}

почему-то это не работает...

* ИЗМЕНИТЬ *

УСПЕХ!

Пришлось создать модуль для размещения внутри повторителя - теперь повторитель выглядит так:

<mx:Repeater id="projRP" width="100%" dataProvider="{projectErrorsAC}">
    <conflict:showErrors id="projErrors" thisObject="{projRP.currentItem}" isProject="true"/>
</mx:Repeater>

и мой модуль выглядит так:

<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init();">
        <mx:Script>
            <![CDATA[
                public var isProject:Boolean;
                public var thisObject:Object;
                [Bindable] public var displayString:String = new String;

                private function init():void
                {
                    if (isProject)
                    {
                        displayString = thisObject.student + " is working on the following projects on the same day: " + thisObject.proj1name + " and " + thisObject.proj2name + ".";
                    }
                }
            ]]>
        </mx:Script>

    <mx:Canvas width="750">
        <mx:HBox>
            <mx:Text id="projmsg" text="{displayString}" />
            <mx:Text id="allow" text="Allow" color="#ff0000" selectable="false" click="parentDocument.acceptProjConflict(thisObject)" mouseOver="parentApplication.switchCursor(true);" mouseOut="parentApplication.switchCursor(false);" />
            <mx:Text text=" |" />
            <mx:Text id="decline" text="Decline" color="#ff0000" selectable="false" click="parentDocument.declineProjConflict(thisObject);" mouseOver="parentApplication.switchCursor(true);" mouseOut="parentApplication.switchCursor(false);" />
        </mx:HBox>
    </mx:Canvas>
</mx:Module>

person Brds    schedule 18.05.2011    source источник
comment
Как именно не работает? Какие ошибки вы получаете?   -  person elekwent    schedule 18.05.2011


Ответы (3)


Это может быть проблема, связанная с ArrayCollection, которая возникает из-за того, что вы пытаетесь удалить объект, который больше не находится в том индексе, который, по вашему мнению, может быть. Я считаю, что именно из-за такого рода проблем Java рекомендует использовать итераторы коллекций.

Дополнительные пояснения здесь

Кроме того, я бы посоветовал вам использовать List с itemRenderer вместо повторителя. Повторители известны своей способностью вызывать утечки памяти и не так оптимизированы, как List с itemRenderers.

Ваше здоровье

person Dennis Jaamann    schedule 18.05.2011
comment
Я не думаю, что это проблема ArrayCollection, но я согласен с использованием List вместо Repeater. - person J_A_X; 18.05.2011
comment
@J_A_X Решает ли компонент DataGroup проблемы, которые есть у Repeater? - person Jason Towne; 18.05.2011
comment
^ Что он сказал. DataGroup лучший :D - person J_A_X; 18.05.2011
comment
Хорошо, я могу понять, что утечка может привести к тому, что элемент окажется не на том месте, где он был раньше... но моя функция acceptProjConflict сравнивает Repeater.currentItem с каждым элементом в рендерере, а затем, когда они совпадают, он удаляет совпавший пункт. - person Brds; 18.05.2011

Во-первых, вы пробовали отладку?

Во-вторых, я удивлен, что обработчик кликов работает, потому что у Repeater есть странные проблемы с областью видимости (которые обычно молча терпят неудачу), поэтому я сказал, что вы должны попытаться отладить.

В-третьих, ваш обработчик кликов неэффективен, вместо этого вы должны сделать что-то вроде этого:

public function acceptProjConflict(conflict:Object):void
{
   for(var i:uint, len:uint = projectErrorsAC.length; i<len; i++)
   {
       if(projectErrorsAC.source[i] == conflict)
       {
           projectErrorsAC.removeItemAt(i);
           break;
       }
   }         
}

Но да, совершенно уверен, что ваша проблема заключается в том, что ваш обработчик никогда не вызывается.

person J_A_X    schedule 18.05.2011
comment
removeItem не является допустимым методом - person Brds; 18.05.2011
comment
О, извините, я думал об ArrayList. Обновлено, чтобы отразить ArrayCollection, но я по-прежнему считаю, что вам следует использовать отладчик, поскольку ваш обработчик, вероятно, даже не вызывается. На самом деле, теперь, когда я об этом думаю, ваш повторитель вообще не работает, поскольку «currentItem» просто используется как итератор, а не поставщик данных, который станет нулевым в конце повторения. Это будет терпеть неудачу каждый раз. Просто используйте список вместо этого. - person J_A_X; 18.05.2011
comment
Да, я пытался вставить простой Alert.show(HI); для первой строки функции... никогда не появляется. Это, скорее всего, займет остаток моего дня (еще 4,5 часа), лол. - person Brds; 18.05.2011
comment
У кого-нибудь есть ссылка на пример списка, который может мне помочь? Я новичок в Flex. Я попытался погуглить, но не могу соединить точки между найденными примерами и тем, что я пытаюсь сделать. - person Brds; 18.05.2011
comment
Если вы новичок в Flex, почему вы используете Flex 3? фуууу. Идти в ногу со временем. А затем, пока вы используете Flex 4, вы можете использовать DataGroup, чтобы делать именно то, что вам нужно. - person J_A_X; 18.05.2011
comment
flex 4 бесплатен для людей с адресом электронной почты @edu, как flex 3? - person Brds; 18.05.2011
comment
Flex бесплатен для всех. Я думаю, что вы говорите о Flash Builder, IDE, которая по-прежнему должна быть бесплатной для обучения. - person J_A_X; 18.05.2011

Вы можете использовать

[Bindable] private var projectErrorsAC:ArrayCollection = []; 

вместо

[Bindable] private var projectErrorsAC:ArrayCollection = new ArrayCollection;

Это будет быстрее, когда у вас есть большие данные.

person mx1810    schedule 03.09.2013