Question

L'UX proposé que j'essaie d'atteindre est le suivant :

  1. l'utilisateur clique sur l'élément de menu (via une sous-classe listBase :par exemple.ButtonBar ou TabBar)
  2. empêcher la sélection initiale
  3. valider si l'utilisateur doit résoudre des problèmes (par ex.données non sauvegardées sur un formulaire, etc.)
  4. si valide, effectuez la sélection et définissez la listBase sur cet index sélectionné, sinon présentez des avertissements à l'utilisateur et annulez complètement le processus de sélection

Cela ne fonctionne pas comme prévu.L'utilisation du type IndexChangeEvent.CHANGING et du PreventDefault permet de tuer la sélection, mais à l'étape 4, lorsque je définis par programme le selectedIndex de listBase, il essaie ensuite de redistribuer l'événement CHANGING (ce malgré ce que prétendent les documents de l'API).

Voici un exemple de code src d'application si vous souhaitez l'essayer par vous-même.J'attends avec impatience vos commentaires et solutions.

Merci.J.

http://snipt.org/vUji3#expand

<?xml version="1.0" encoding="utf-8"?>
<s:Application minWidth="955" minHeight="600"
           xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx"
           xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
    <![CDATA[
        import flash.utils.setTimeout;

        import mx.core.mx_internal;

        import spark.events.IndexChangeEvent;

        use namespace mx_internal;

        [Bindable]
        private var doPreventDefault:Boolean;

        [Bindable]
        private var delayMS:uint = 500;

        private function buttonbar_changingHandler( event:IndexChangeEvent ):void
        {
            // TODO Auto-generated method stub
            if ( doPreventDefault )
            {
                event.preventDefault();

                setTimeout( delayedLogic, delayMS, event.newIndex );
            }
        }

        private function delayedLogic( index:int ):void
        {
            //disabling this results in an endless loop of trying to set the selected index
            //              doPreventDefault = false;

            //this should NOT be hitting the changing handler since we're supposed to be dispatching a value commit event instead.
            bb.setSelectedIndex( index, false );
        }
    ]]>
</fx:Script>

<fx:Declarations>

    <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>

<s:layout>
    <s:VerticalLayout horizontalAlign="center"/>
</s:layout>

<s:ButtonBar id="bb"
             changing="buttonbar_changingHandler(event)">
    <s:dataProvider>
        <s:ArrayList>
            <fx:String>btn 0</fx:String>
            <fx:String>btn 1</fx:String>
            <fx:String>btn 2</fx:String>
        </s:ArrayList>
    </s:dataProvider>
</s:ButtonBar>

<s:CheckBox label="preventDefault?"
            selected="@{ doPreventDefault }"/>

<s:NumericStepper maximum="5000" minimum="500"
                  stepSize="500" value="@{ delayMS }"/>
</s:Application>
Était-ce utile?

La solution

En regardant le SDK, le IndexChangeEvent.CHANGING l'événement est en fait évitable - malgré la documentation ici dit que annulable est faux, donc je suis mauvais sur ce point (même si ASDoc est allé un peu de travers), mais les choses deviennent un peu intéressantes à partir de là.

Dans ListBase @1296, ceci n'est distribué que depuis le commitSelection(dispatchEvents:Boolean = true) méthode.Dans ButtonBarBase:dataProvider_changeHandler() est le seul endroit qui appelle spécifiquement à ne pas envoyer l'événement, mais à ListBase, on l'appelle commitProperties@939 lorsqu'il existe un proposéSelectionIndex.

Donc, à partir de votre code ci-dessus, si vous essayez de définir la sélection, cela appellera commitSelection, ce qui, je crois, est à l'origine du problème de la pile d'appels.Le délai du Timer ne fera qu'exacerber le problème, car à 500 ms, l'interface utilisateur aura traversé son cycle d'invalidation au moins une fois, ce qui signifie que commitSelection sera à nouveau exécuté en raison d'un invalidateProperties le drapeau est placé à partir du proprosedSelectionIndex issue finalement de setSelectedIndex @729

Alors, comment résoudre ce problème.
J'envisagerais de faire la prévention uniquement si la validation échoue, sinon je lui permettrais de se dérouler normalement.En cas d'échec, appelez le service de prévention, définissez un errorString ou équivalent, mais n'essayez pas de modifier la sélection.

[modifier] Lisez le commentaire de RiaStar, et je viens d'être d'accord avec la même « solution ».

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top