注意:使用哈希表中的值的时候尽量使用properties.AfterProperties[properties.ListItem.Fields["Closed Reasons"].InternalName] 这种形式,否则容易没有值。

转自http://www.cnblogs.com/icedog/archive/2010/12/07/1899589.html
EventHandler给我们在MOSS中开发带来了很大的自由度,很方便地就捕获到在数据操作时的事件,插入相应的业务代码,实现我们的业务逻辑。在使用了好长一段时间EventHandler后,忽然想归纳一下我这段时间在使用EventHandler时遇到的问题,给大家分享一下!

 

1. 在ItemAdding事件或ItemUpdating事件中获取用户输入的值
        这是一个很普通的操作,通常我们都会遇到这样一个业务逻辑:只有当用户输入的值符合要求才允许用户添加记录,否则取消该操作;或者在用户添加一条记录时,获取用户输入的值,再去进行其它操作。遇到这些业务,必须的是要在ItemAdding事件中获取到用户用户的值,那我们自然就会很想到一个属性properties.ListItem,这是正在添加的记录项,但恰恰这是添加前的事件,properties.ListItem的值为Null,并不能获取得到,就算在ItemUpdating事件中,properties.ListItem虽然是有值,但并不是用户输入的最新的值,而是原来的值(旧值)。
        想在记录项添加时或修改时得到新的值,我们可以直接使用下面的语句
        properties.AfterProperties["Title"].ToString();

2. 在ItemAdding事件或ItemUpdating事件中修改该记录项的值
        我们有时候在设计列表的时候,会添加一些对用户隐藏的栏,用于记录与该记录相关的信息,只能通过程序去改写此栏的值,那我们在添加新记录项或修改记录项时怎样修改该栏的值呢?很自然,我们会写出下面的程序
public override void ItemUpdating(SPItemEventProperties properties)
{
    SPListItem item 
= properties.ListItem;
     item[
"Title""这是我指定的值";
     item.Update();
}

    但很抱歉,运行这段的下场只有一个——出错!系统会报出“保存冲突”的错误信息。回头仔细看看代码,代码在记录项正在修改时,再次修改了该记录项。与SQL相似,MOSS也会在进入ItemUpdating事件前,把该记录项上了锁,以防止该记录项在没完成本次修改前给再次修改,因此这样写注定是失败的!如果是在ItemAdding事件更是如此,在前文说了,在ItemAdding事件时,properties.ListItem的值为Null,该记录项都还没生成,所以根本不可能也不应该通过properties.ListItem来修改某个栏上的值,因为properties.ListItem所表示的是一个记录项旧的值(新增前的旧值没是没有,null)
    那通过什么属性来修改呢?MOSS一定会提供一个途径给我们做这事的!我们再来关注一下properties.AfterProperties这个属性,从字面意思可以很容易知道,这是记录项新的值,但很可惜,这个属性是只读的,我们也不能直接修改这个属性达到我们的目的。接着往下看,在properties.AfterProperties中还有一个属性ChangedProperties,连起来看,properties.AfterProperties.ChangedProperties字面意思很像是该属性保存该字段改变了的值(SDK也是这样说的,Gets properties that have changed in the collection),这很容易就理解成MOSS会自动比较用户修改了记录的哪些值,开始的时候,我也是这样理解的,但很奇怪,无论我怎样修改记录的值,在调试时,该属性值的Count属性始终是0,并不如我开始所想的!
     那时在网上查了很多资料,都只是说奇怪MS为什么会提供ChangedProperties这样一个HashTable类型的属性,而且始终是没有值放到里面去的。在一次反编译MS的官方站点模板中的EventHandler事件程序时,我才恍然大悟!我们应该这样理解ChangedProperties这个HashTable,它是用于给我们修改栏值的一个集合,我觉得SDK的英文应该改成“Gets properties that will be changed in the collection”才对(个人见解),因为在ItemAdding事件或ItemUpdating事件中,记录项并没有真的生成或修改,ListItem代表的是原来的值,AfterProperties代表的是这个记录项将要变成的值,共中的ChangedProperties提供再次修改的一次机会。所以,要在ItemAdding事件或ItemUpdating事件中修改该记录项的值得在这样写 EventHandle(转)

public override void ItemAdding(SPItemEventProperties properties)

{
    
// Demo1: 在新建时取用户输入的值并作修改
    string newValue "新的值是:+ properties.AfterProperties["Title"].ToString();   //应该使用这种形式properties.AfterProperties[properties.ListItem.Fields["Closed Reasons"].InternalName]  
    properties.AfterProperties.ChangedProperties.Add(
"Title", newValue);
}

 

===================================

正如你所知道的,事件接收器(EventHandler)非常强大,可以挂在许多SharePoint事件上。它们可以应用于功能(Feature)事件,如FeatureActivated,列表事件,如FieldAdded,等等。然而,其中我们最常用的还是SPItemEventReceiver中的一系列接收器。通过继承该类,我们可以把自己的代码挂接在列表项或文档库文档上发生的一系列事件上。

当你利用这些事件时,就很快会发现存在前(同步)后(异步)两种事件。其方法的后缀分别为“ing”(比如,ItemAdding)和“ed”(比如,ItemAdded),分别代表了变更发生前调用和发生后调用。这些都是最基本的东西。

接下来,当你更深入时甚至发现,你可以提取变更前和变更后的状态变化。比如,我们可以挂接到一个文档库的ItemUpdating事件上,来阻止用修改某个特定的字段。其代码大致如下:

 

  public override void  ItemUpdating(SPItemEventProperties properties)
  {
       if (properties.BeforeProperties["column"] != properties.AfterProperties["column"])
//使用properties.AfterProperties[properties.ListItem.Fields["Closed Reasons"].InternalName] 
 
      {
          properties.Cancel = true;
          properties.ErrorMessage = "该栏不允许修改";
      }
  }

对于文档库而言,该代码运行良好。然而,你应该知道,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的值进行比较。代码如下:

 

  if (properties.ListItem["column"] != properties.AfterProperties["column"])
  {
      properties.Cancel = true;
      properties.ErrorMessage = "该栏不允许修改";
  }

相关文章:

  • 2022-12-23
  • 2021-09-28
  • 2022-02-11
  • 2021-11-18
  • 2021-11-05
  • 2021-10-06
  • 2021-11-17
  • 2021-10-14
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-06-25
  • 2022-12-23
  • 2022-12-23
  • 2021-11-06
相关资源
相似解决方案