Work-around to render the custom field in list view
Once I got a request from one of colleagues to create custom button field which will kick off a workflow for the list item which it get associated. Then, I had created a custom field which inherited from SPFieldText and rendered an ASP.net button control and in the click event I have implemented the code to kick off the workflow.
Everything worked fine and field rendered perfectly in the New, Edit, and Display form. But in the list view it doesn’t shows the button, we can see the column name in the list but can’t see the button in the list item. Below is the code that I have used to create the field and the FLDTypes.xml file.
ButtonFieldWF.Field.cs
1: using System;
2: using System.Runtime.InteropServices;
3: using System.Security.Permissions;
4: using Microsoft.SharePoint;
5: using Microsoft.SharePoint.WebControls;
6: using Microsoft.SharePoint.Security;
7:
8: namespace CustomButtonField
9: {
10: // TODO: Replace, as needed, "SPFieldText" with some other class derived from SPField.
11: // TODO: Update, as needed, ParentType element in fldtypes*.xml in this solution.
12: [CLSCompliant(false)]
13: [Guid("4a71f8a6-a7d1-45bb-9ced-8ed1676c95d6")]
14: public class ButtonFieldWFField : SPFieldText
15: {
16: public ButtonFieldWFField(SPFieldCollection fields, string fieldName)
17: : base(fields, fieldName)
18: {
19:
20: }
21:
22: public ButtonFieldWFField(SPFieldCollection fields, string typeName, string displayName)
23: : base(fields, typeName, displayName)
24: {
25: }
26:
27: public override BaseFieldControl FieldRenderingControl
28: {
29: [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
30: get
31: {
32: BaseFieldControl fieldControl = new ButtonFieldWFFieldControl();
33: fieldControl.FieldName = this.InternalName;
34:
35: return fieldControl;
36: }
37: }
38:
39:
40: }
41: }
ButtonFieldWF.FieldControl.cs
1: using System;
2: using System.Runtime.InteropServices;
3:
4: using Microsoft.SharePoint;
5: using Microsoft.SharePoint.WebControls;
6: using Microsoft.SharePoint.Workflow;
7:
8: using System.Web;
9: using System.Web.UI;
10: using System.Web.UI.WebControls;
11: using System.Web.UI.HtmlControls;
12:
13: namespace CustomButtonField
14: {
15: // TODO: Replace, as needed, "TextField" with some other class derived from Microsoft.SharePoint.WebControls.BaseFieldControl.
16: [CLSCompliant(false)]
17: [Guid("9fbee449-9f7f-48de-999b-d7187dfe78cf")]
18: public class ButtonFieldWFFieldControl : TextField
19: {
20:
21: private Button oBtnWF = null;
22:
23: protected override void CreateChildControls()
24: {
25: base.CreateChildControls();
26:
27:
28: if (this.ControlMode == SPControlMode.Edit || this.ControlMode == SPControlMode.New || this.ControlMode == SPControlMode.Display)
29: {
30: oBtnWF = new Button();
31: oBtnWF.Text = "Start the custom WF";
32: oBtnWF.Click += new EventHandler(oBtnWF_Click);
33: base.Controls.Add(oBtnWF);
34:
35: }
36: }
37:
38: void oBtnWF_Click(object sender, EventArgs e)
39: {
40:
41: SPSite oSite = this.ListItem.Web.Site;
42:
43: //get the workflow associated with this doc lib and kick if off
44: if (this.List.WorkflowAssociations.Count > 0)
45: {
46: // kick off the first workflow..you can kick off your custom workflow by taking it properly
47: SPWorkflowAssociation wrkFl = this.List.WorkflowAssociations[0];
48: oSite.WorkflowManager.StartWorkflow(this.ListItem, wrkFl, wrkFl.AssociationData, true);
49: }
50: System.Web.HttpContext.Current.Response.Write("started...");
51:
52: }
53:
54: protected override void Render(HtmlTextWriter output)
55: {
56: this.oBtnWF.RenderControl(output);
57: }
58: }
59: }
fldtypes_ButtonFieldWF.xml
1: <?xml version="1.0" encoding="utf-8"?>
2: <FieldTypes>
3: <FieldType>
4: <Field Name="TypeName">ButtonFieldWFField</Field>
5: <Field Name="TypeDisplayName">ButtonFieldWFField</Field>
6: <Field Name="TypeShortDescription">ButtonFieldWFField</Field>
7: <Field Name="ParentType">Text</Field>
8: <Field Name="UserCreatable">TRUE</Field>
9: <Field Name="FieldTypeClass">4a71f8a6-a7d1-45bb-9ced-8ed1676c95d6</Field>
10: </FieldType>
11: </FieldTypes>
After doing research on this issue confirmed that, by default we can’t render any controls like button, imagebutton, etc in list view. Because the items are rendering in the list view through CAML and <![CDATA [ html goes here ] ], so here the only work-around is construct the control using CDATA and display it.
1: <?xml version="1.0" encoding="utf-8"?>
2: <FieldTypes>
3: <FieldType>
4: <Field Name="TypeName">ButtonFieldWFField</Field>
5: <Field Name="TypeDisplayName">ButtonFieldWFField</Field>
6: <Field Name="TypeShortDescription">ButtonFieldWFField</Field>
7: <Field Name="ParentType">Text</Field>
8: <Field Name="UserCreatable">TRUE</Field>
9: <Field Name="FieldTypeClass">4a71f8a6-a7d1-45bb-9ced-8ed1676c95d6</Field>
10: <RenderPattern Name="DisplayPattern">
11: <Switch>
12: <Expr>
13: <Column Name="ContentTypeId" />
14: </Expr>
15: <!-- This is the Content Type Id for FOLDERs -->
16: <Case Value="0x012000499529A73A47A1408DC7541F73C144CE">
17: <!-- We do not want to display anything for folders -->
18: </Case>
19: <Default>
20:
21: <!-- This is the List ID -->
22: <!-- ListProperty Select="Name" / -->
23:
24: <HTML>
25: <![CDATA[<input type="button" onClick="Test();" value="Start the custom WF" id="btn_]]>
26: </HTML>
27: <Column Name="ID" />
28: <HTML>
29: <![CDATA[" />]]>
30: </HTML>
31:
32: <HTML>
33: <![CDATA[
34: <script type="text/javascript" language="javascript">
35:
36: function Test()
37: {
38: alert('hiii');
39: }
40: </script>
41:
42: ]]>
43: </HTML>
44:
45: </Default>
46: </Switch>
47: </RenderPattern>
48: </FieldType>
49: </FieldTypes>
But, here another obstacle was the execution of server side code to kick off the workflow. We can’t write the server side code in <! [CDATA [] ]>, so we can kick off the workflow by putting that code in the page load of an aspx page and open it while clicking the button.
(eg : window.open(“_layouts/custompage.aspx”)).
Another work-around would be adding an ECB menu item for the list item and implement this functionality while clicking on it.
Also please check this How-To video to know how we can create custom fields in WSS 3.0, if you are not familliar with this already.