柔性:Spark 上的 PreventDefault:ListBase 不工作
-
13-12-2019 - |
题
我想要实现的建议用户体验是这样的:
- 用户单击菜单项(通过 listBase 子类:例如按钮栏或选项卡栏)
- 阻止初始选择
- 验证用户是否需要解决问题(例如表单上未保存的数据等)
- 如果有效,则进行选择并将 listBase 设置为 selectedIndex,否则向用户显示警告并完全取消选择过程
这并不像您期望的那样工作。利用 IndexChangeEvent.CHANGING 类型和 PreventDefault 可以终止选择,但在步骤 4 中,当我以编程方式设置 listBase 的 selectedIndex 时,它会尝试重新调度 CHANGING 事件(尽管 API 文档声称如此)。
如果您想亲自尝试一下,这里是一个示例应用程序 src 代码。我期待您的意见和解决方案。
谢谢。J
<?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
尽管有文档说明,事件实际上是可以预防的 这里 说cancelable是假的,所以我对此很不满意(尽管ASDoc有点偏离),但是事情从这里开始变得有点有趣。
在 ListBase @1296 中,这仅从 commitSelection(dispatchEvents:Boolean = true)
方法。在 ButtonBarBase:dataProvider_changeHandler()
是唯一专门调用不分派事件的地方,但在 ListBase
, ,它被称为 commitProperties
@939 当有提议的选择索引时。
因此,从上面的代码来看,如果您尝试设置选择 - 这将调用 commitSelection,我认为这会导致调用堆栈问题。计时器延迟只会加剧问题,因为在 500 毫秒时,UI 将至少经历一次失效周期,这意味着 commitSelection 将再次执行,因为 invalidateProperties
标志正在设置 proprosedSelectionIndex
最终源于 setSelectedIndex
@729
那么如何解决这个问题。
我只会考虑在验证失败时进行预防,否则允许其正常进行。如果确实失败,请调用阻止,设置 errorString
或同等内容,但不要尝试更改选择。
[编辑] 阅读 RiaStar 的评论,我只是同意相同的“解决方案”。