1

私が達成しようとしている提案されたUXはこれです:

  1. ユーザーがメニュー項目をクリックします(listBaseサブクラスを介して:例:ButtonBarまたはTabBar)
  2. 初期選択を防ぐ
  3. ユーザーが問題に対処する必要があるかどうかを検証します(たとえば、フォームに保存されていないデータなど)
  4. 有効な場合は、選択を行い、listBaseをそのselectedIndexに設定します。そうでない場合は、ユーザーに警告を表示し、選択プロセスを完全にキャンセルします。

これは期待どおりに機能しません。IndexChangeEvent.CHANGINGタイプとpreventDefaultを利用すると、選択が強制終了されますが、ステップ4で、listBaseのselectedIndexをプログラムで設定すると、CHANGINGイベントが再ディスパッチされます(これは、APIドキュメントの主張にかかわらず)。

これを自分で試してみたい場合は、サンプルのアプリケーションsrcコードを次に示します。コメントと解決策を楽しみにしています。

ありがとう。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>
4

1 に答える 1

1

SDKを見ると、IndexChangeEvent.CHANGINGイベントは実際には防止可能です。ここのドキュメントにはキャンセル可能は誤りであると記載されているので、(ASDocは少し横向きになりましたが)それは悪いことですが、ここから少し興味深いものになります。

ListBase @ 1296では、これはcommitSelection(dispatchEvents:Boolean = true)メソッドからのみディスパッチされます。InButtonBarBase:dataProvider_changeHandler()は、イベントをディスパッチしないように特に呼び出す唯一の場所ですが、inは、proposedSelectionIndexがある場合に@939ListBaseで呼び出されます。commitProperties

したがって、上記のコードから、選択を設定しようとしている場合、これはcommitSelectionを呼び出します。これにより、呼び出しスタックの問題が発生していると思います。タイマーの遅延は問題を悪化させるだけです。500msでUIは少なくとも1回無効化サイクルを経ているため、最終的に@ 729に由来するinvalidatePropertiesフラグが設定されているため、commitSelectionが再度実行されます。proprosedSelectionIndexsetSelectedIndex

だからこれを修正する方法。
検証が失敗した場合にのみ防止を実行することを検討します。それ以外の場合は、通常どおり続行します。それが失敗した場合は、preventを呼び出し、errorStringまたは同等のものを設定しますが、選択を変更しようとしないでください。

[編集]RiaStarのコメントを読んで、私は同じ「解決策」に同意しました。

于 2012-10-04T15:40:11.750 に答える