Вопрос

Предлагаемый UX, которого я пытаюсь достичь, таков:

  1. пользователь щелкает элемент меню (через подкласс listBase:напримерButtonBar или TabBar)
  2. предотвратить первоначальный выбор
  3. проверить, нужно ли пользователю решать проблемы (например,несохраненные данные в форме и т. д.)
  4. если это действительно так, сделайте выбор и установите для listBase этот выбранный индекс, в противном случае выдайте пользователю предупреждения и полностью отмените процесс выбора.

Это работает не так, как вы ожидаете.Использование типа IndexChangeEvent.CHANGING и PreventDefault работает, чтобы отменить выбор, но на шаге 4, когда я программно устанавливаю selectedIndex в listBase, он затем пытается повторно отправить событие CHANGING (несмотря на то, что утверждает документация API).

Вот пример исходного кода приложения, если вы хотите попробовать это самостоятельно.Я с нетерпением жду ваших комментариев и решений.

Спасибо.Дж

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>
Это было полезно?

Решение

Глядя на SDK, IndexChangeEvent.CHANGING событие на самом деле можно предотвратить - несмотря на документацию здесь говорит, что отмена является ложной, так что я в этом виноват (хотя ASDoc пошел немного не так), однако отсюда все становится немного интереснее.

В ListBase @1296 это отправляется только из commitSelection(dispatchEvents:Boolean = true) метод.В ButtonBarBase:dataProvider_changeHandler() это единственное место, которое специально призывает не отправлять событие, но в ListBase, это вызвано commitProperties@939, когда есть предложенныйSelectionIndex.

Итак, из вашего кода выше, если вы пытаетесь установить выбор - это вызовет commitSelection, что, как я считаю, вызывает проблему со стеком вызовов.Задержка таймера только усугубит проблему, поскольку через 500 мс пользовательский интерфейс хотя бы один раз пройдет цикл аннулирования, а это означает, что commitSelection будет выполнен снова из-за invalidateProperties флаг устанавливается из proprosedSelectionIndex в конечном итоге вытекающие из setSelectedIndex @729

Итак, как это исправить.
Я бы рассмотрел возможность предотвращения только в случае сбоя проверки, в противном случае разрешил бы ей работать как обычно.Если это не удалось, вызовите функцию предотвращения, установите errorString или эквивалент, но не пытайтесь изменить выбор.

[править] Прочитайте комментарий RiaStar, и я только что согласился с тем же «решением».

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top