SharePoint takes a lot of criticism from developers but it is really impressive what you can do without writing backend code. In my last large SharePoint implementation, I was customizing some input fields for a form using SharePoint Designer. I found myself looking at the XSLT for a DataFormWebPart wondering how to decipher the auto-generated _designer:bind attribute.
<SharePoint:FormField runat="server" id="ff1{$Pos}" ControlMode="Edit" FieldName="Field1" __designer:bind="{ ddwrt:DataBind( 'u', concat('ff1',$Pos), 'Value', 'ValueChanged' 'ID', ddwrt:EscapeDelims(@ID), '@Field1' )}" />
Strangely, the method ddwrt:DataBind is absent from what is probably the best online overview of the ddwrt XSLT extension object. So I threw the question onto Stack Overflow to see if any bright people could shed light on the mysterious method. Not surprisingly, no one could answer the question. So I decided to do some spelunking in Reflector to see what I could find.
I opened reflector, added a reference to Microsoft.SharePoint then opened the search window. Using the “Member Search” (tip: CTRL+M) I searched for "DataBind" and found the internal class, Microsoft.SharePoint.WebPartPages.DataFormDdwRuntime. Some parts of this assembly are obfuscated, but by guestimation this is likely the extension object that is available to us in the XSLT under the namespace "ddwrt".
Oddly enough, the DataFormDdwRuntime.DataBind method returns an empty string, so it’s likely that the “__designer:bind” attribute is just a dummy attribute for SharePoint Designer, if at all. Remember that curly braces inside an attribute is an XSLT expression, so the computed result is actually __designer:bind=””. The real magic is that what the DataBind method actually does.
Behind the DataBind Method
Turns out that the DataBind method is basically a wrapper to the DataFormWebPart method, AddDataBinding. This method has the following signature:
public override void AddDataBinding(string op, string controlId, string propertyName, string eventName, string keyField, string keyValue, string dataField )
As the name implies, it creates a data binding and associates it with the hosted WebPart, but the msdn documentation leaves us guessing as to what values should be used. Reflector provides us some guidance.
Note: keyField, keyValue and dataField all refer to methods that are obfuscated. The detail below for these fields is my best guess, so take it AS-IS with no warranty. As always, your comments, suggestions and feedback are welcome.
Operation Type (“op”)
This is the type of operation that will be used when the form is submitted. There are three possible values: "i” (Insert), “u” (Update") and “d” (Delete). The logic falls back to “update” if it doesn’t recognize the value passed in.
Bound Control (“controlId”)
This the id of the control that will be will be bound to the SharePoint list item. The auto-generated value attempts to duplicate the value of the “id” attribute using an xslt function concat. You can use your own format, but the chosen format for the id’s are “ff + field index + record index” where the field index is an arbitrary number, usually the order in which the fields appear in the designer (1,2,3, etc), and the keyword $Pos is an XSLT variable defined earlier in scope, referring to the position() of the row in the result set.
Bound Control Property (“propertyName”)
This is the property on our bound control that will ultimately be used to represent the SharePoint field value. For SharePoint FormField controls, this property is “Value”. Most ASP.NET controls can be used, assuming that the propertyName and eventName are properly set.
Bound Control Event (“eventName”)
This the event on the bound control that you want to be handled when the form posts information back to the server. How this works is really interesting: it uses reflection to get the Event of your control, then binds the postback event to the DataFormWebPart's HandleChangedField method. This method essentially fetches the value of your control (via the PropertyName) and then tracks that the field has changed or needs to be inserted.
For SharePoint FormField controls, this event is “ValueChanged”.
Data Source Primary Key (“keyField”)
Based on examples, the “key field” refers to the attribute in the dsQueryResponse XML which represents the primary key for this record. This is likely always going to be "ID". (ie, /dsQueryResponse/Rows/Row/@ID)
Data Source Primary Key Value (“keyValue”)
The value of the primary key, “ID”. The ddwrt:EscapeDelims method is used to convert certain characters (,=;'{}") to a SharePoint unicode string equivalent (ie, “,” is converted to “_x002C_”). For SharePoint Designer XSLT, this is likely always going to be ddwrt:EscapeDelims(@ID).
Data Source Field Name (“dataField”)
This is the name of the SharePoint field that we want to bind. Since we’re pulling this value from the dsQueryResponse XML, it’s represented as it appears in the dsQueryResponse XML.
Some Examples
Updating a SharePoint text field using an ASP.NET TextBox:
<asp:TextBox runat="server" id="myTextBox{$Pos}" Text="{@Field1}" Value="{@Field1}" __designer:bind="{ddwrt:DataBind( 'u', concat('myTextBox', $Pos), 'Text', 'TextChanged', 'ID', ddwrt:EscapeDelims(@ID), '@Field1')}" />
Insert a SharePoint text field as a ASP.NET DropDownList:
<asp:DropDownList runat="server" id="myDropDown{$Pos}" __designer:bind="{ddwrt:DataBind( 'i', concat('myDropDown', $Pos), 'SelectedValue', 'TextChanged', 'ID', ddwrt:EscapeDelims(@ID), '@Field2'}" />
Conclusion
If you’re using the auto-generated XSLT, the default format works fine. However, if you want to craft the markup by hand or roll your own customizations, understanding this syntax is helpful.