1

我试图实现的建议用户体验是这样的:

  1. 用户单击菜单项(通过 listBase 子类:例如 ButtonBar 或 TabBar)
  2. 防止初始选择
  3. 验证用户是否需要解决问题(例如表单上未保存的数据等)
  4. 如果有效,则进行选择并将 listBase 设置为该 selectedIndex,否则向用户显示警告并完全取消选择过程

这不像您预期​​的那样工作。利用 IndexChangeEvent.CHANGING 类型和 preventDefault 可以杀死选择,但是在第 4 步,当我以编程方式设置 listBase 的 selectedIndex 时,它会尝试重新调度 CHANGING 事件(尽管 API 文档声称这样做)。

如果您想亲自尝试,这里是一个示例应用程序 src 代码。我期待您的评论和解决方案。

谢谢。Ĵ

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>
4

1 回答 1

1

查看 SDK,该IndexChangeEvent.CHANGING事件实际上是可以预防的——尽管这里的文档说可取消是错误的,所以我对此不好(尽管 ASDoc 有点侧身),但是事情从这里开始变得有点有趣。

commitSelection(dispatchEvents:Boolean = true)在 ListBase @1296 中,这只会从方法中分派。InButtonBarBase:dataProvider_changeHandler()是唯一专门调用不调度事件的地方,但在 中,当有提议的SelectionIndex 时ListBase,它会在@939 中调用。commitProperties

因此,从上面的代码中,如果您尝试设置选择 - 这将调用 commitSelection,我认为这会导致调用堆栈问题。Timer 延迟只会加剧问题,因为在 500 毫秒时,UI 将至少经历一次失效周期,这意味着 commitSelection 将再次执行,因为最终源自@729的invalidateProperties标志被设置proprosedSelectionIndexsetSelectedIndex

那么如何解决这个问题。
如果验证失败,我只会考虑进行阻止,否则允许它正常进行。如果确实失败,请调用 prevent、set anerrorString或等效项,但不要尝试更改选择。

[编辑] 阅读 RiaStar 的评论,我同意相同的“解决方案”。

于 2012-10-04T15:40:11.750 回答