Wednesday 19 December 2007

Creating a WebPart with Custom User Control

The following is a very good article on how to create various options in your WebPart.

http://bloggingabout.net/blogs/mglaser/archive/2007/04/19/building-my-own-usercontrol-webpart-part-vi.aspx

Friday 14 December 2007

Creating Custom Field Control

In this example we are creating a custom field type which concatenates two text fields (first and last name).
Create a new usercontrol file (customfieldcontrol.ascx). In this usercontrol, add a SharePoint:RenderingTemplate control, and insert whatever you want for your control template.

Secondly, create a new class file (customfieldcontrol.cs), which will take the role of codebehind file of the usercontrol. In this class, which will inherit from Microsoft.SharePoint.WebControls.BaseFieldControl, we will override some of the properties and methods to implement our own logic.
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace CustomControl
{
public class customfieldcontrol : BaseFieldControl
{
protected TextBox txtFirstName;
protected TextBox txtLastName;

protected override string DefaultTemplateName
{
get { return "CustomFieldRendering"; }
}
public override object Value
{
get
{
EnsureChildControls();
return txtFirstName.Text + "%" + txtLastName.Text;
}
set
{
try
{
EnsureChildControls();
txtFirstName.Text = value.ToString().Split('%')[0];
txtLastName.Text = value.ToString().Split('%')[1];
}
catch { }
}
}
public override void Focus()
{
EnsureChildControls();
txtFirstName.Focus();
}
protected override void CreateChildControls()
{
if (Field == null) return;
base.CreateChildControls();

//Don't render the textbox if we are just displaying the field
if (ControlMode == Microsoft.SharePoint.WebControls.SPControlMode.Display) return;

txtFirstName = (TextBox)TemplateContainer.FindControl("txtFirstName");
txtLastName = (TextBox)TemplateContainer.FindControl("txtLastName");
if (txtFirstName == null) throw new NullReferenceException("txtFirstName is null");
if (txtLastName == null) throw new NullReferenceException("txtLastName is null");
if (ControlMode == Microsoft.SharePoint.WebControls.SPControlMode.New)
{
txtFirstName.Text = "";
txtLastName.Text = "";
}
}
}
}Actually, what this code does is:Define the ID of the renderingtemplate control in our usercontrol.Set the return value to the value we want it to return :), in this case this will be something like Firstname%Lastname.Make sure that when you edit an item, the proper values are filled in into the textboxes again.
Next thing to do is to create the Field type class (CustomField.cs) itself. In this class, which derives of one of the base control types from SharePoint (SPFieldText, SPFieldChoice, ...), we will define which control has to be used as template, and which value has to be returned when displaying a list item.
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace CustomControl
{
public class CustomField : SPFieldText
{
public CustomField(SPFieldCollection fields, string fieldName)
: base(fields, fieldName)
{ }

public CustomField(SPFieldCollection fields, string typeName, string displayName)
: base(fields, typeName, displayName)
{ }

public override BaseFieldControl FieldRenderingControl
{
get
{
BaseFieldControl fieldControl = new customfieldcontrol();
fieldControl.FieldName = this.InternalName;
return fieldControl;
}
}

public override string GetValidatedString(object value)
{
return value.ToString().Split('%')[1].ToUpper() + " " + value.ToString().Split('%')[0];
}
}
}Main thing of this code is the GetValidatedString() function. This function defines what is to be displayed when you display an item (in a list view for example).In our case, which in our case will be something like LASTNAME Firstname.
Last file to create is the XML File (fldtypes_custom.xml), which will add the custom field type to SharePoint.



CustomField
Text
Custom Name Field
Custom Name Text Field
TRUE
TRUE
TRUE
TRUE
TRUE
TRUE
TRUE
CustomControl.CustomField, CustomControl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxx
nvarchar


So far so good with creating the files :) Now, all we have to do is put the right files in the right places ...Compile your project (or at least both .cs classes) and make sure they are strong named.Then, install them in the GAC (%windir%\assembly)Next, copy the .ascx file to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\CONTROLTEMPLATESAnd the last file to copy: copy the .xml file to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\XML
That's it. Maybe do an IISRESET, and you can use your newly created Custom Field Type!

As taken from Nick's SharePoint Blog. Another good practical example is:

http://www.kcdholdings.com/blog/?p=56

Creating Custom Field Controls

Steps involved in creating a SharePoint Custom Field Control


1. Create your field definition in FLDTYPES_xxx.XML file, and add FieldEditorUserControl property to your custom field definition. Define fields for all custom properties of your custom field definition in PropertySchema section. Set Hidden attribute of all Field elements in PropertySchema section to True. Otherwise, fields will be rendered in user interface.

Example, a custom property definition looks like:

MyCustomField
My Custom Field
Text
MyFields.MyCustomField, MyFields, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f3bf8ec1b42660c3
TRUE
TRUE
/_controltemplates/MyCustomFieldControl.ascx





...




2. Create .ascx control file in TEMPLATE\CONTROLTEMPLATES directory. In my sample it’s MyCustomFieldControl.ascx and is very simple:














This control has only one drop-down control. The idea is, that user can select some value from drop-down, and it’ll be stored in custom property of our custom field.

3. Create .NET classes for your custom field type and user control. For custom field type:

As you can see, we’ve created string attribute and property, for my field type’s CustomProperty. In Init method, we populate it with stored custom property value. Finally, we overridden Update method, to save modified custom property values to the field.


The code for my user control:
public class SelectMyCustomProperty : UserControl, IFieldEditor
{
/* ... */
public void OnSaveChange(SPField field, bool isNew)
{
string value = this.ctlMyCustomProperty.SelectedValue;
MyCustomField myField = field as MyCustomField;
if(isNew)
myField.UpdateMyCustomProperty(value);
else
myField.MyCustomProperty = value;
}
/* ... */
}
As described in SDK user control class should implement IFieldEditor interface. It has 2 methods and 1 property:
InitializeWithField – is called, when control is initialized;
OnSaveChanged – called, when user clicks OK button in field properties window;
DisplayAsNewSection – true if control should be displayed as new section in field properties form.
In CreateChildControls we just populate our drop-down list with some values.

The crucial point here is, not to try setting values directly to custom properties in OnSaveChange (like, myField.SetCustomProperty(“MyCustomProperty”, value)). Even if you call myField.Update() afterwards, the value won’t be saved! More precisely, it will be saved, but then it will be overwritten by current custom property value. Looks like SharePoint calls OnSaveChange in our control, then continues to update values of custom properties from other sources (and our Hidden field in PropertySchema section is one of them), and finally calls field’s Update method. That’s why we need to override Update method in our custom field class and set custom property values there – at that point SharePoint has done his job, and won’t change any property values.

Wednesday 12 December 2007

SharePoint 2007: Approval Workflow - using SharePoint Groups are Approvers

Recently, I was setting up an Approval workflow. To make administration of the workflow easier, I created SharePoint Groups (e.g. Workflow Approvers), which I assigned as the Approvers of the workflow.

This makes it easier for the Site Administrators to change the Approvers, because they just find the group and edit the members of the group, rather than having to edit the actual workflow.

Strangely, when a workflow was kicked off and a task assigned to the group, once one of the Approvers had approved the item, a task was being set to the System Account user. Thus the approval workflow was not completing.

To solve the issue, you'll need to:
Tick the checkbox "Assign a single task to each group entered (Do not expand groups)” in add a workflow page, no one can be done by any one of participants.

Also check the checkbox Complete this workflow when Following number of tasks are finished and then enter 1 in the text below. This will complete the approval process when one of the user approves it.

Wednesday 5 December 2007

SharePoint Solutions Blog: Deploying Web Parts with Solution Packages in WSS v3/MOSS 2007

How to deploy a SharePoint 2007 Web Part as a feature:

SharePoint Solutions Blog: Deploying Web Parts with Solution Packages in WSS v3/MOSS 2007