Friday, January 7, 2011

SPItemEventReceiver < Data >: how to use it and where

I m sure you aware of this piece of xml code if you ever use the custom SPItemEventReceiver :
<Elements><Receivers> <Receiver>
Every time you want to associate your custom EventReceiver with a specific list you have to create a feature with element which will describe the association :
<Receivers ListTemplateId="{your listtemplate id}">
    <Receiver>
      <Name>ItemAddedAutoTitleEventHandler</Name>
      <Type>ItemAdded</Type>
      <SequenceNumber>10000</SequenceNumber>
      <Assembly>SE.SharePoint.blog, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a4607a0133bbaeb2</Assembly>
      <Class>SE.SharePoint.blog.EventHandlers.AutoPropagateTitleEventReceiver</Class>
      <Data></Data>
      <Filter></Filter>
    </Receiver>
  </Receivers>
Here is not very informative but still a lot referenced msdn documention about it

Couple weeks ago I got curious about the most overlooked element <Data>. Msdn promises me that It contains a string that is used to pass parameters to the receiver.
Ok, fair enough. But I couldn't find a real example why I would need it!
...and I've found!
I have created a AutoPropagateTitleEventReceiver which is responsible for a title propagation after the listitem creation.
A pretty common task in the sharepoint proiects...but I found that every time ppl tend to stick with their own specific class for every listtemplate or even create a SPD (Sharepoint Designer) Workflow!
I am not really against nor specific event handlers, not SPD Wf... but I feel that this task can be perfectly perfom within one common class...if only pass the rule "how the title can be constructed"....
 Wait a minute!   <Data></Data> - that' s perfect for a string based rule\pattern!
So the short story short - I have created the pattern rule  - in my case the an internal name of fields from where the value should be gathered to put it in the title  in my general eventreceiver:
private void setTitle(SPItemEventProperties properties)
        {
          
            StringBuilder title = new StringBuilder();
            SPListItem item = properties.ListItem;
            //pattern ex: <Data>InternalName1#InternalName2</Data> ;

            string titlePattern = properties.ReceiverData;
            string[] columns = titlePattern.Split('#');
          
            foreach (string column in columns)
            {
                if(item.Fields.ContainsField(column))
                {
                    SPFieldLookupValue lookupV =null;
                    string columnValue;
                    try
                    {
                        lookupV = new SPFieldLookupValue(item[column].ToString());
                    }
                    catch
                    { }
                     
                       if (lookupV != null)
                       {
                           columnValue = lookupV.LookupValue;
                       }
                       else
                       {
                           columnValue=item[column].ToString();
                       }


                       title.AppendFormat(" {0}", columnValue);
                }
            }
          
            object titleF =item.Fields["Title"];
            if(!String.Equals(titleF.ToString(),title.ToString()))
            {
                item["Title"] = title.ToString();
                this.DisableEventFiring();               
                item.Update();
                this.EnableEventFiring();
            }
        }

There is only one thing left - add association to the list where I need to autogenerate the title:
<Receivers ListTemplateId="{your listtemplate id}">
    <Receiver>
      <Name>ItemAddedAutoTitleEventHandler</Name>
      <Type>ItemAdded</Type>
      <SequenceNumber>10000</SequenceNumber>
      <Assembly>SE.SharePoint.blog, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a4607a0133bbaeb2</Assembly>
      <Class>SE.SharePoint.blog.EventHandlers.AutoPropagateTitleEventReceiver</Class>
      <Data>InternalColumn1#InternalColumn2</Data>
      <Filter></Filter>
    </Receiver>
  </Receivers>

For every list I want to  have the AutoPropagateTitleEventReceiver  I need to add the element with related ListTemplateId . And at some point probably I will need a specific logic in the receiver for a particular list. No big problem - I can always create an additional specific event handler and add as second; using  the sequence number to control what receiver will go first.

Happy sharepointing!