理解 Flex itemEditor-第 2 部分:編輯事件和複雜編輯器

理解 Flex itemEditor-第 2 部分:編輯事件和複雜編輯器

轉載 http://www.adobe.com/cn/devnet/flex/articles/itemrenderers_pt1.html

 

在本系列的第 1 部分中,您已經看到如何創建一些簡單的內聯 itemEditor。如果您閱讀過 itemRenderer 系列,您可能會發現兩者十分相似。

使 itemEditor 能正常運行有兩個要點。首先,使用 itemEditor 屬性命名類。其次,使用 editorDataField 屬性命名 itemEditor 的 value 屬性。

在本文中,我將說明如何使用事件創建更復雜的 itemEditor,它們可以執行一些簡單的數據驗證操作並且可以防止他人編輯某些單元格。

這裏請注意一點:這裏的“複雜”並不不是指包含許多控制和佈局的編輯器。我指的是比內聯 itemEditor 複雜一些。我認爲要求用戶在 DataGrid 的列表或單元格中進行復雜編輯時不公平的。編輯器應當只關注一件事:單元格的內容。例如,如果您使用列表控制並展示一個購物車,那麼允許用戶直接編輯單元格中的值來更改購物車中的商品數量無可厚非。但允許他們更改商品本身、顏色、特殊說明等內容是不合理的。換言之,允許他們直接從購物車購買商品並不合理,因爲整個站點都可以購買商品。購物車只是方便他們結帳而已。當然,他們應該可以再加一罐冰激凌或拿掉一包薯片,但不可以把薯片換成兩盒全麥意大利麪。

 

itemEditEnd 事件

假設您的應用程序有一個 DataGrid 用於協助管理庫存。用戶可以使用它更改部件號,但您不希望允許他們將部件號留空。如果使用默認 itemEditor,即 TextInput 控制,用戶可以單擊“Part #”列中的單元格,按 delete 鍵並擦除部件號。以下代碼通過實施一種技術來防止這種情況。

         <mx:DataGrid x="10" y="64" editable="true" dataProvider="{inventoryDB}" 
                 itemEditEnd="verifyInput(event)">
                 <mx:columns>
                          <mx:DataGridColumn headerText="Product" dataField="product"/>
                          <mx:DataGridColumn headerText="Part #" dataField="part"/>
                          <mx:DataGridColumn headerText="Type" dataField="type"
                                   itemEditor="editors.ProductTypeEditor" editorDataField="type"/>
                          <mx:DataGridColumn headerText="Quantity" dataField="quantity"/>
                 </mx:columns>
         </mx:DataGrid>

每當編輯即將完成時,列表控制調度一個 itemEditEnd 事件。在數據提交回 dataProvider 之前,事件發生。通過處理該事件,您可以更改數據,或驗證數據並根據情況停止提交。在此例中,verifyInput() 函數確保產品部件號不空。

                 private function verifyInput( event:DataGridEvent ) : void
                 {
                          // it is OK if the user cancels the edit
                          if( event.reason == DataGridEventReason.CANCELLED ) return;
                          
                          // grab the instance of the itemEditor. For this DataGrid, only the
                          // TextInput control is used as the editor, so it is safe to get the
                          // editor no matter what column has been edited.
                          var editor:TextInput = (event.currentTarget as DataGrid).itemEditorInstance as TextInput;
                          
                          // if  the edit is on the part number column, make sure it is not blank
                          if( event.dataField == "part" )
                          {
                                   if( editor.text.length == 0 ) {
                                            // call event.preventDefault() so the edit will not continue and store the
                                            // blank value
                                            event.preventDefault();
                                            // give the editor an error to display to the user
                                            editor.errorString = "You must enter a part number";
                                            return;
                                   }
                          }
                          
                          // handle other columns here
                 }

該事件是 DataGridEvent 類的一個實例,它包含一些很實用的屬性。reason 屬性說明調度該事件的原因。如果用戶按下 ESCAPE 鍵或單擊 DataGrid 以外區域,原因是 DataGridEventReason.CANCELLED。您可能希望像我那樣忽略該事件,告訴 DataGrid 只需執行默認操作,即取消編輯並恢復先前值。

如果決定處理該事件,您需要 itemEditor 才能訪問其屬性。事件的 currentTarget 屬性包含控制,我已經將它轉換爲 DataGrid。DataGrid 包含一個 itemEditorInstance 屬性,我將它轉換爲 TextInput,對於本例,它屬性 itemEditor 類型。

因爲將爲任何單元格調用該事件處理程序,所以您必須決定您是否想驗證編輯。我檢查事件的 dataField 屬性,確保單元格在“part”列中。如果是,我測試編輯器的 text 屬性,查看它是否包含任何字符。如果沒有字符,會發生兩件事。

首先,會調用 event.preventDefault()。我通過這種方式防止編輯操作,並防止 DataGrid 將新值恢復回 dataProvider 中。對於用戶而言,他們在按下 TAB 或 ENTER 鍵後,似乎未發生任何事。preventDefault() 函數將 itemEditor 保留在原位。

其次,我將一個 errorString 放到 TextInput 控制上。這是可選的,但它卻是會告訴用戶出錯了。畢竟,當他們按下 TAB 或 ENTER 鍵時,未發生任何事,此時應當提供一個理由。

itemEditBeginning 事件

有時您可能希望防止單元格被編輯。您可以將 DataGridColumn 的可編輯屬性設置爲 false,但這會防止每個單元格被編輯。假設您只希望將列中的某些單元格變爲無法編輯?您可以使用 itemEditBeginning 事件指定某個單元格是否可編輯。

    <mx:DataGrid x="10" y="64" editable="true" dataProvider="{inventoryDB}" 
        itemEditEnd="verifyInput(event)" 
        itemEditBeginning="allowForEdit(event)">
        <mx:columns>
            <mx:DataGridColumn headerText="Product" dataField="product"/>
            <mx:DataGridColumn headerText="Part #" dataField="part"/>
            <mx:DataGridColumn headerText="Type" dataField="type"
                itemEditor="editors.ProductTypeEditor" editorDataField="type"/>
            <mx:DataGridColumn headerText="Quantity" dataField="quantity"/>
        </mx:columns>
    </mx:DataGrid>

通過處理 itemEditBeginning 事件,您可以動態決定單元格的可編輯性。在本例中,數據的每個記錄中包含一個名爲 permanent 的字段。我們的想法是 permanent=true 表示產品名是一個無法更改的值,因而無法編輯該行的產品單元格。它由 allowForEdit() 函數處理:

        private function allowForEdit(event:DataGridEvent) : void
        {
            // if the field to be edited is a product, prevent the user from making
            // changes if the permanent flag is true<. You can use more complex logic, 
            // of course.
            if( event.dataField == "product" ) {
                
                var item:Object = ((event.currentTarget as DataGrid).dataProvider as ArrayCollection)[event.rowIndex];
                if( item.permanent ) {
                    event.preventDefault();
                }
            }
            
            // handle other columns here
        }

再次說明,該事件是 DataGridEvent 類的一個實例,我在此處已檢查事件的 dataField 屬性,確保它是我正在處理的“product”字段。隨後,我可以使用事件的 currentTarget 屬性從 DataGrid 的 dataProvider 獲得記錄,並將它轉換爲 DataGrid。隨後,我將 DataGrid 的 dataProvider 轉換爲 ArrayCollection 並獲得 event.rowIndex 值。我也可以在這個函數中直接訪問 inventoryDB ArrayCollection,因爲它們在同一文件中,但這個方法更普通。

獲得記錄後,我就可以查詢其參數屬性以及它是否爲 true,調用 event.preventDefault() 函數來禁用該單元格的編輯操作。在此例中,itemEditBeginning 的默認行爲是顯示 itemEditor;阻止默認行爲將使該單元格無法編輯。

編輯限制

必須注意,處理編輯事件時要考慮到一些限制。當您使用編輯事件決定是否應繼續事件時,您可能希望調用後端或服務器進程。例如,您可能有一個可驗證部件號的 Web 服務。此時,您可以在 itemEditEnd 事件中嘗試執行 Web 服務調用並驗證用戶剛纔輸入的內容。看上去符合邏輯,對嗎?

似乎符合邏輯,但實際不可行,因爲服務調用是異步的。您當然可以執行調用,但稍後才能返回結果-這要等到事件處理程序退出之後了。事實上,在您的函數退出之前不會執行調用。您的調用將排隊,並在 Flex 框架退出函數時執行請求,隨後由 Web 服務的結果處理程序返回結果。

所以在編輯單元格時,無法執行這類服務器端驗證。如果要執行這類驗證,那麼當您的應用程序啓動時,您應當向服務器查詢要驗證的數據,並在編輯單元格時使用它。

後續工作

動態允許編輯和驗證更改的能力可以大幅改善應用程序的用戶體驗。您可以幫助用戶減少錯誤並在編輯過程中提出反饋。您可以防止他們編輯特定數據並簡化應用程序開發,因爲您不必驗證用戶無法更改的內容。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章