1

为了说明 Q。我真的会过度简化示例(实际上代码更加复杂)。

假设您有一个 flex 控件,它下面包含一个数据网格。就像是

<mx:DataGrid id="grid" dataProvider="{document.items}">
    <mx:columns>
        <mx:DataGridColumn headerText="Column 1" dataField="@name"/>
        <mx:DataGridColumn headerText="Column 2" dataField="@value"/>
    </mx:columns>
</mx:DataGrid>

其中 document 是一个模型对象,包含一些数据。您在控件上提供了一个选择设置器,因为客户端不想知道有关底层数据模型的任何信息:

public function set selectedItem(title:String):Allocation
{
   grid.selectedItem  = null;

   for each(var o:Object in grid.dataProvider)
   {
      var t:String = o.@title;
      if( t == title )
      {
         grid.selectedItem = o;
         return;
      }
   }
}

到目前为止,一切都很好。如果预先填充了 document.items,则选择将正常工作。然而。如果您在应用程序启动时已经知道选择应该是什么 - 它已经(例如)在 URL 上传递,该怎么办?所以,在 flex 中你可能有类似的东西

// Initialising now...
mycontrol.document = this.document; // give the control the document

// Fetch titles
new FetchTitlesEvent().dispatch(); // cairngorm-style event

// Set the selection 
mycontrol.selectedItem = Application.application.parameters.title;

哎呀。因为 FetchTitlesEvent 是异步操作的,当时 mycontrol.selectedItem 是无法工作的。不知何故,我们需要(重新)触发该代码以设置控件上的选择。现在,我有几种方法可以做到这一点,但都有代码气味:

1) 在获取完成后,在 FetchTitlesCommand 中执行此操作 - 这会污染需要知道这一点的视图(或视图s )的命令。感觉就像一场等待发生的维护噩梦,这意味着视图完全绑定到命令,并且这些命令不可重用。布莱赫。

2)当它完成时从事件中回调(或者做一些复合命令,从 FetchTitlesEvent 开始,以一个新命令结束来做集合)。对我来说似乎很脆弱 - 维护者如何知道需要哪些回调?它仍然将 UI 控制知识绑定到命令中。坏事。

3)有某种计时器,等待事件队列静止几秒钟。骇客骇客。

4)在控制中进行。绑定到 document.items 上 mycontrol 中的 collectionevents,监视更改。一旦与选择匹配的行到达,选择它并停止监视更改。- 控制感觉是做这件事的正确地方 - 收集事件有时会引发令人兴奋的 CHANGE 或 REFRESH 事件 - 似乎是一个昂贵的监视器

我非常倾向于(4)。flex-ers 之前是否使用过任何其他选项来解决这个问题 - 特别是是否有任何我可能使用的库编入代码,因为它必须是一个相当通用的问题?

4

4 回答 4

2

您可以将selectedItem控件的属性设置为 Bindable Object 变量:

<mx:Script>
    <![CDATA[
        [Bindable]
        private var mySelectedItem:Object;
    ]]>
</mx:Script>

<mx:DataGrid id="grid" dataProvider="{document.items}" selectedItem="{mySelectedItem}">
    <mx:columns>
        <mx:DataGridColumn headerText="Column 1" dataField="@name"/>
        <mx:DataGridColumn headerText="Column 2" dataField="@value"/>
    </mx:columns>
</mx:DataGrid>

这样就可以随时设置或重置 selectedItem,控件会根据 Object 更新 selectedItem。例如,您可以在初始化事件、创建完成事件或任何其他函数中设置处理程序。设置变量时,您可能需要在控件上调用 validateNow(),如果在初始化期间设置变量,则可能需要在控件的 creationComplete 上调用。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="initializeHandler();">
    <mx:Script>
        <![CDATA[
            [Bindable]
            private var mySelectedItem:Object;

            private function initializeHandler():void
            {
                mySelectedItem = getSelectedItem(); // your logic to determine the initial item to select
            }

            ....

            private function grid_creationCompleteHandler():void
            {
                grid.validateNow();
            }
        ]]>
    </mx:Script>

    <mx:DataGrid id="grid" dataProvider="{document.items}" selectedItem="{mySelectedItem}" creationComplete="grid_creationCompleteHandler();">
        <mx:columns>
            <mx:DataGridColumn headerText="Column 1" dataField="@name"/>
            <mx:DataGridColumn headerText="Column 2" dataField="@value"/>
        </mx:columns>
    </mx:DataGrid>
</mx:Application>
于 2009-03-26T14:44:42.453 回答
1

如果我正确理解您的问题,正确的方法是使用 creationComplete 事件。flex 中的所有 UI 对象都会广播一个 creationComplete 事件,让您知道一切何时完成并准备就绪。您可以在网格本身上侦听 creationComplete 事件,也可以在应用程序上侦听它,因为它不会广播,直到它的所有子项(即一切)都被创建为止。

于 2009-03-26T12:44:08.547 回答
0

尝试使用 ChangeWatcher

var cw:ChangeWatcher = ChangeWather.watch(this, ["document","items"], 
function(e:Event):void
{
    //check to see if the data we want to select has arrived

    //once we've selected the data, we don't need this handler anymore
    cw.unwatch();
});

请原谅任何语法错误,我面前没有 FB。

于 2009-03-31T02:22:17.610 回答
0

不幸的是,这不是一个创建完成的问题——问题不是控件的初始化,而是数据的初始化。由于它是异步的,因此您不知道它最终何时到达。

于 2009-03-26T12:55:36.427 回答