正如你所知道的,事件接收器(EventHandler)非常強大,可以掛在許多SharePoint事件上。它們可以應用於功能 (Feature)事件,如FeatureActivated,列表事件,如FIEldAdded,等等。然而,其中我們最常用的還是 SPItemEventReceiver中的一系列接收器。通過繼承該類,我們可以把自己的代碼掛接在列表項或文檔庫文檔上發生的一系列事件上。
當你利用這些事件時,就很快會發現存在前(同步)後(異步)兩種事件。其方法的後綴分別為“ing”(比如,ItemAdding)和“ed”(比如,ItemAdded),分別代表了變更發生前調用和發生後調用。這些都是最基本的東西。
接下來,當你更深入時甚至發現,你可以提取變更前和變更後的狀態變化。比如,我們可以掛接到一個文檔庫的ItemUpdating事件上,來阻止用修改某個特定的字段。其代碼大致如下:
1 public override void ItemUpdating(SPItemEventProperties properties)
2 {
3 if (properties.BeforeProperties["column"] != properties.AfterProperties["column"])
4 {
5 properties.Cancel = true;
6 properties.ErrorMessage = "該欄不允許修改";
7 }
8 }
對於文檔庫而言,該代碼運行良好。然而,你應該知道,BeforeProperties哈希表對於列表項來說並不公開。用SDK中的原話說:“對於文檔,Before 和 After 屬性可為發布事件(例如 ItemUpdated)提供保證,但 Before 屬性不能用於有關列表項的發布事件。”。
當他們說“不能用於有關列表項的發布事件”時,意思是說在後事件(比如 ItemUpdated,ItemDeleted等)中不可用嗎?這裡詞語表述不是很清楚,因此我決定花點時間測試一下各種常見事件(像添加,修改和刪除)與列表和庫的組合。每個測試包括了添加一個新項,編輯該項,然後刪除該項。下面是對列表的測試結果:
列表 BeforeProperties AfterProperties properties.ListItem ItemAdding 沒值 新值 空 ItemAdded 沒值 新值 新值 ItemUpdating 沒值 更改的值 老值 ItemUpdated 沒值 更改的值 更改的值 ItemDeleting 沒值 沒值 老值 ItemDeleted 沒值 沒值 空
“沒值”的意思是該欄的值在哈希表中不可用。
“新值”的意思是該欄當前的值是可用的。
“更改的值”的意思是該欄修改後的值是可用的。
“老值”的意思是該欄在修改前的值是可用的。
下面是對於文檔庫的測試結果:
文檔庫 BeforeProperties AfterProperties properties.ListItem ItemAdding 沒值 沒值 空 ItemAdded 沒值 沒值 新值 ItemUpdating 老值 更改的值 老值 ItemUpdated 老值 更改的值 更改的值 ItemDeleting 沒值 沒值 老值 ItemDeleted 沒值 沒值 空
Properties.ListItem是指列表項在事件中當前的值。空表示該項不可用。通過我的分析得到如下結論:
毫不奇怪,我們在ItemAdding(在項被添加前)和ItemDeleted(在項被刪除後)得到的是空值。之前Lshai Sagi也證明過這一點。
正如SDK中記載的,對於列表項事件不公開BeforeProperties。
對於列表項而言ItemAdding 和ItemAdded正確返回了AfterProperties的值,而對於庫文件則無效。這一點很有意思。
通過之前的實驗發現,在ItemDeleted中沒有任何可用的值。這也很明顯,一旦刪除了就徹底消失了。
因此,如果再回到我們原來的問題上,如何防止用戶在列表項的事件中修改某一欄的值?對於列表而言,你可以看到,如果掛在ItemUpdating事件上,我們可以對當前列表項的值(properties.ListItem)和AfterProperties的值進行比較。代碼如下:
1 if (properties.ListItem["column"] != properties.AfterProperties["column"])
2 {
3 properties.Cancel = true;
4 properties.ErrorMessage = "該欄不允許修改";
5 }
本文中我們為你使用列表和文檔庫前後事件提出一些好的建議。希望能看到你的更好的想法或反饋。