zoukankan      html  css  js  c++  java
  • EventHandler中需要注意的事件

    项目中有个需求,需要一个列表联动九个其它列表,调试起来很费时间,也发现了EventHandler中的一些使用技巧,下面的内容大部分是转载,也有自己的心得,具体出处忘了,如果作者看到,请谅解。

    1. ItemAdding事件或ItemUpdating事件中获取用户输入的值

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

            properties.AfterProperties["Title"].ToString();

             如果字段为汉字名,那就要取InternalName了,如下


                    using (SPWeb web = (properties.OpenWeb()) as SPWeb)
                    
    {
                        SPList List 
    = web.Lists[properties.ListTitle] as SPList;
                        sNameTitle 
    = List.Fields["所属部门"].InternalName;
                        Orgname 
    = properties.AfterProperties[sNameTitle].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事件中修改该记录项的值得在这样写


    using (SPWeb web = (properties.OpenWeb()) as SPWeb)
     
    {
       SPList List 
    = web.Lists[properties.ListTitle] as SPList;   //取得当前修改的List
       sNameTitle = List.Fields["组织编码"].InternalName;        //取得字段的名字
       string test01 = PItem["组织编码"].ToString();
       properties.AfterProperties.ChangedProperties.Add(sNameTitle, PItem[
    "组织编码"]); //将修改的值赋给当前eventhandler的item
     }

    注意事项:

     在进行ItemUpdating,ItemAdding,ItemDeleting编程时,会有两个不同的动作,事件首先会锁定当前ListItem,就是说你甭想改了,然后在Afterproperties中存放将要提交的修改值,这时你可以通过ChangeProperties来修改这个将要提交的值,BeforeProperties这个比较奇怪,什么时候都取不到,基本上没用过。
    DisableEventFiring()及EnableEventFiring(),这是一组必要的方法,特别是在Updating和Updated事件中,但也要视具体情况而定,如果涉及到联动其它列表的,一般会DisableEventFiring()
    int Value1 = Convert.ToInt32(properties.AfterProperties[Field_InternalName].ToString());

    int Value2 = Convert.ToInt32(properties.BeforeProperties[Field_InternalName].ToString());

    properties.AfterProperties.ChangedProperties[Field_InternalName] = intInterval2;

    尽量先确定前两个,再根据选择使用第三个. 此外如果前两点所述方法都报异常(在写ItemDeleting时会出现),那么则需要获得现在数据库里的值,可以这样做:

     try
     
    {
            String swhere 
    = SyList.Fields["身份证号"].InternalName;
            String svalue 
    = item["身份证号"].ToString();
            SyQry 
    = new SPQuery();
            SyQry.Query 
    = "<Where><Eq><FieldRef Name='" + swhere + "'/><Value Type='Text'>" + svalue + "</Value></Eq></Where>";
            result 
    = SyList.GetItems(SyQry);
            
    return result;
     }

     
    catch (Exception ex)
     
    {
       log.Error(ex.ToString());
       
    throw ex;
     }

    列表的事件调试是个力气活,特别是关联列表比较多的时候,做一个好的数据关系图,是一个良好的习惯,然后就是你需要一个良好的错误捕捉机制,多用log4net(见我上篇文章),在生产环境中可以很轻易的捕捉到错误来自哪里,否则你就哭去吧。


  • 相关阅读:
    RabbitMQ资料
    在网页打开本地程序的思路
    HttpClient的巨坑
    webbrowser设置为相应的IE版本
    cpupower:Shows and sets processor power related values
    golang 国内环境配置
    OSX 创建 randisk(或称 tmpfs)
    Gentoo 搭遗
    ubuntu 去除开机背景
    fabric && cita 调研对比
  • 原文地址:https://www.cnblogs.com/georgehu/p/1423782.html
Copyright © 2011-2022 走看看