Silverlight自定義資料繫結控制元件應該如何處理IEditableObject和IEditableCollectionView物件
原創文章,如需轉載,請註明出處。
最近在一直研究Silverlight下的資料繫結控制元件,發現有這樣兩個介面IEditableObject 和IEditableCollectionView,記錄一下結論,歡迎交流指正。
本文會重點介紹在構建Silverlight自定義資料繫結控制元件的過程中,我們會對資料來源進行操作,那麼就會碰到上述兩個介面,如何正確的處理它們。
1. IEditableObject
我在MSDN上查了一下,這個概念早在.Net 1.0的時候就提出了,但是我一直沒有關注過這個東東。
What is IEditableObject?
IEditableObject is used to represent an object that has an editing mode and the ability to commit or revert changes.
UseCase:When a validation error occurs in a cell, user can back out of changes using Escape key. However if user has made changes to other columns in same row, those changes will still persists.User may wish to back out of all changes. This is where IEditableObject interface comes into play. IEditableObject is used to represent an object that has an editing mode and the ability to commit or revert changes.
Definition:
public interface IEditableObject
{
void BeginEdit();
void CancelEdit();
void EndEdit();
}
簡單來說IEditableObject就是具有編輯模式,並且支援整體提交和回滾值的物件。比如一個數據行物件,你可以更改其多個列的值,在沒有提交者前,都可以通過CancelEdit進行回滾。
通過一個簡單的Memo模式就可以實現這個物件。
2. IEditableCollectionView
這個概念是在WPF3.5 SP1的時候才引入,目的是提供一個具有事務能力的集合類。
IEditableCollectionView is a new collection view that you can use to supports adding and removing new items, as well as editing items in a transactional way. It is implemented by ListCollectionView (the default view for ObservableCollection) and BindingListCollectionView (the default view for DataTable).
Definition:
public interface IEditableCollectionView { bool CanAddNew { get; } bool CanCancelEdit { get; } bool CanRemove { get; } object CurrentAddItem { get; } object CurrentEditItem { get; } bool IsAddingNew { get; } bool IsEditingItem { get; } NewItemPlaceholderPosition NewItemPlaceholderPosition { get; set; } object AddNew(); void CancelEdit(); void CancelNew(); void CommitEdit(); void CommitNew(); void EditItem(object item); void Remove(object item); void RemoveAt(int index); }
這兩個介面的關係:
When the data Item implements IEditableObject, the IEditableCollectionView will call BeginEdit() when a new item is added or an existing item is opened for edit. It will call CancelEdit() when the item is cancelled and EndEdit() when the item is committed. IEditableCollectionView lets the app author handle this part of the transaction.
換句話說就是,如果IEditableCollectionView發現其Item實現了IEditableObject介面,會在它的EditItem,CommitEdit以及CancelEdit方法中呼叫子Item的BeginEdit,EndEdit和CancelEdit方法。
3. 自定義資料繫結控制元件應該如何處理這兩個介面
IEditableObject
如果資料繫結控制元件發現當前行繫結的物件是IEditableObject,那麼在該行上如果有一個Cell進入編輯狀態,並且是第一個單元格的時候,就需要呼叫繫結物件的BeginEdit方法。
當某一行上某一個Cell處於編輯狀態的時候,Press Esc,該Cell會退出編輯狀態,值也會回滾。注意這個時候不會呼叫IEditableObject的CancelEdit方法,這是Cell本身應該提供的行為。這個時候IsEdit為False,但是Row擁有焦點,繼續Press Esc,會呼叫IEditableObject的CancelEdit方法,你會發現其他列的值也會回滾。
當某一行上某一個Cell處於編輯狀態的時候,滑鼠點選其他行,該Cell會退出編輯狀態。只是會呼叫IEditableObject的EndEdit方法。
IEditableCollectionView
對於IEditableCollectionView來說,EditItem,CommitEdit還有CancelEdit方法分別對應著IEditableObject介面的BeginEdit,EndEdit和CancelEdit,呼叫時機完全一樣。
資料繫結控制元件如果其資料來源是IEditableCollectionView, 在處理BeginEdit,EndEdit和CancelEdit的時候應該直接呼叫CollectionView的相應方法,這個時候就不需要在處理 IEditableObject介面了,IEditableCollectionView內部會呼叫該介面。
只有在其資料來源不是IEditableCollectionView的時候,如果Row繫結物件是IEditableObject,需要呼叫IEditableObject的介面實現。
這樣的話,自定義資料繫結控制元件就可以完美支援這兩個介面了。
說明:以上描述是以Silverlight DataGrid為例,自定義控制元件類似。