Skullcrusher's Blog

Andy Bonner's Blog at vbCity

vbCity Blogs moved to:
http://cs.vbcity.com/blogs
  Home :: Syndication  :: Login

Congratulations! You've managed to stumble across the mad rantings of Andy Bonner aka Skullcrusher

Here you'll find all sorts of hopefully useful info on MOSS (Microsoft Office SharePoint Server) and things .NET related. You might even find other useful gems if I get around to it.


You can contact me on the address below, but I won't guarantee a response 8-}

JunJuly 2009Aug
SMTWTFS
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

Articles

Archives

Topics

Image Galleries

MOSS/SharePoint Links

Well it's been a long time since my last post and I though I'd better get my arse into gear and share some of the stuff I've been working on. As part of some development work I was doing for a colored SharePoint Calendar I had the need to allow users to select colors to have different types of Events displayed in and couldn't find a decent way of accomplishing this with the built in components of SharePoint, so I decided that this was an ideal candidate for a custom field type. Having made what I think is a useful addition to SharePoint I thought I'd share it with you. First I'll give you a little flavour of what it looks like before we dive into the code and how it all hangs together

 

Here's how the field first looks in a New or Edit form


Here's some of the color choices available


And this is what it looks like once you've made some choices


So thats what the field looks like when your using it but how does it display you might be wondering, well here's how you'd see it in a list view

Yep lovely but not very practicle is it, the real power comes when you use this value either within code or the xslt of the DataView WebPart, then you can produce some quite stunning results.

 

custom xslt using the field values


Custom calendar views using the field values through code


So Now that you've seen what you can do with it let's get into the code itself. In this example we have 5 files

  • SPColorsPickerFieldValue which inherits from SPFieldMultiColumnValue and holds the values and describes the properties for our field
  • SPColorsPickerField which inherits from SPFieldMultiColumn and is our field
  • SPColorsPickerFieldControl which inherits from BaseFieldControl and is the brains of the operation, basically the code behind for our ASCX
  • ControlTemplates_SPColorsPicker.ascx which defines a SharePoint RenderingTemplate element that tells it how to render our field in New or Edit mode
  • fldtypes_SPColorsPicker.xml which basically describes our field to SharePoint, telling it where it can be used, what it's called, what the assembly is called & also how it should be rendered in a list view

So how do we create a project for this custom field you ask. Well just create a Class Library project within VS2005 & add references for Microsoft.SharePoint and Microsoft.SharePoint.Security which you'll find in C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI.

You also need to sign the assembly with a strong name key. Then you'll need to add classes for the field, field value & field control. Each of these classes needs a unique guid attribute. Here's the 3 classes you need

SPColorsPickerFieldValue (holds the values and describes the properties for our field)

Code CopyHideScrollFull
using System;
using
System.Collections.Generic;
using
System.Text;
using
Microsoft.SharePoint;
using
System.Runtime.InteropServices;

namespace
SPColorsPicker
{
[CLSCompliant(false)]
[Guid("7B5DF376-E7DB-4353-AD51-7C5B69C675D6")]
[Serializable]
public
class SPColorsPickerFieldValue : SPFieldMultiColumnValue
{
//how many properties are we storing
private
const int numberOfFields = 2;
//required constructor
public
SPColorsPickerFieldValue()
: base(numberOfFields)
{
}
//required constructor
public
SPColorsPickerFieldValue(string value)
: base(value)
{
}

//property for storing the font color to use

public
string FontColor
{
get
{
if (string.IsNullOrEmpty(this[0]))
return "Black";
else
return this[0];
}
set
{ this[0] = value; }
}
//property for storing the background color to use
public
string BackgroundColor
{
get
{
if (string.IsNullOrEmpty(this[1]))
return "White";
else
return this[1];
}
set
{ this[1] = value; }
}
}
}
. . .

SPColorsPickerField (our field)

Code CopyHideScrollFull
using System;
using
System.Collections.Generic;
using
System.Text;
using
System.Runtime.InteropServices;
using
Microsoft.SharePoint;
using
Microsoft.SharePoint.WebControls;

namespace
SPColorsPicker
{
[CLSCompliant(false)]
[Guid("01FB13ED-33F3-4caa-8CCF-42DAE083291F")]
public
class SPColorsPickerField : SPFieldMultiColumn
{
//required constructor
public
SPColorsPickerField(SPFieldCollection fields, string fieldName)
: base(fields, fieldName)
{
}
//required constructor
public
SPColorsPickerField(SPFieldCollection fields, string typeName, string displayName)
: base(fields, typeName, displayName)
{
}
//tell it which control to use for rendering this field
public
override BaseFieldControl FieldRenderingControl
{
[SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
get

{
BaseFieldControl fieldControl = new SPColorsPickerFieldControl();
fieldControl.FieldName = this.InternalName;
return fieldControl;
}
}
//returns the value of this field
public
override object GetFieldValue(string value)
{
if (String.IsNullOrEmpty(value))
return null;
return new SPColorsPickerFieldValue(value);
}
}
}
. . .

SPColorsPickerFieldControl (the brains)

Code CopyHideScrollFull
using System;
using
System.Collections.Generic;
using
System.Text;
using
Microsoft.SharePoint.WebControls;
using
System.Web.UI.WebControls;
using
System.Runtime.InteropServices;
using
System.Reflection;
using
System.Web.UI;
using
System.Drawing;

namespace
SPColorsPicker
{
[CLSCompliant(false)]
[Guid("F44DCD6A-D657-42e8-853A-ABC0713773C2")]
public
class SPColorsPickerFieldControl : BaseFieldControl
{
protected DropDownList ddlBackground;
protected
DropDownList ddlFont;
protected
TextBox tbSampleText;
private SPColorsPickerFieldValue fieldValue;
protected override string DefaultTemplateName
{
//Get the RenderingTemplate in the ascx file
get
{ return "ColorsPicker"; }
}
public override object Value
{
get
{
EnsureChildControls();
if
(this.ControlMode != SPControlMode.Display)
{
GetValues();
}
return
fieldValue;
}
set

{
EnsureChildControls();
fieldValue = value as SPColorsPickerFieldValue;
}
}
private void GetValues()
{
//set this instances value to whats been selected
fieldValue.FontColor = ddlFont.SelectedItem.Text;
fieldValue.BackgroundColor = ddlBackground.SelectedItem.Text;
}
private void SetValues()
{
//set the controls values to whats currently stored in the field for an existing item
ddlFont.SelectedItem.Text = fieldValue.FontColor;
ddlBackground.SelectedItem.Text = fieldValue.BackgroundColor;
tbSampleText.ForeColor = Color.FromName(fieldValue.FontColor);
tbSampleText.BackColor = Color.FromName(fieldValue.BackgroundColor);
}
protected override void OnInit(EventArgs e)
{
//either get the value from an existing item or set it as a new value
if
(ControlMode == SPControlMode.Edit || ControlMode == SPControlMode.Display)
{
if (this.ListItemFieldValue != null)
fieldValue = this.ListItemFieldValue as SPColorsPickerFieldValue;
else
fieldValue = new SPColorsPickerFieldValue();
}
if (ControlMode == SPControlMode.New)
{
fieldValue = new SPColorsPickerFieldValue();
}
base.OnInit(e);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if
(!Page.IsPostBack && ControlMode != SPControlMode.Display)
{
//fill the DropDowns with the list of available colors
List
<string> allColors = new List<string>(Enum.GetNames(typeof(System.Drawing.KnownColor)));
List
<string> systemColors = new List<string>();
foreach (MemberInfo member in (typeof(System.Drawing.SystemColors)).GetProperties())
{
systemColors.Add(member.Name);
}
foreach (string color in allColors)
{
if (!systemColors.Contains(color))
{
this.ddlBackground.Items.Add(color);
this
.ddlFont.Items.Add(color);
}
}
//register scripts to update the preview client side
ClientScriptManager cs = this.Page.ClientScript;
if (!cs.IsClientScriptBlockRegistered(this.GetType(), "ChangeColors"))
{
StringBuilder csText = new StringBuilder();
csText.Append(" <SCRIPT type=text/javascript>");
csText.Append("function changeTextColor(dropdown, textboxID)");
csText.Append("{");
csText.Append("var x = document.getElementById(textboxID);");
csText.Append("var myindex = dropdown.selectedIndex;");
csText.Append("var SelValue = dropdown.options[myindex].value;");
csText.Append("x.style.color = SelValue;");
csText.Append("}");
csText.Append("function changeBackgroundColor(dropdown, textboxID)");
csText.Append("{");
csText.Append("var x = document.getElementById(textboxID);");
csText.Append("var myindex = dropdown.selectedIndex;");
csText.Append("var SelValue = dropdown.options[myindex].value;");
csText.Append("x.style.backgroundColor = SelValue;");
csText.Append("}");
csText.Append("</SCRIPT> ");
cs.RegisterClientScriptBlock(this.GetType(), "ChangeColors", csText.ToString(), false);
}
SetValues();
}
}
protected override void CreateChildControls()
{
if (Field == null)
return;
base.CreateChildControls();
if (ControlMode == SPControlMode.Display)
return;
//set the local vaiables
ddlFont = (DropDownList)TemplateContainer.FindControl("ddlFont");
ddlBackground = (DropDownList)TemplateContainer.FindControl("ddlBackground");
tbSampleText = (TextBox)TemplateContainer.FindControl("tbSampleText");
if (!Page.IsPostBack)
{
//add attributes to call the javascript functions when we choose different colors from the dropdown box's
//to update the preview client side

string
textboxID = this.tbSampleText.ClientID;
ddlBackground.Attributes.Add("OnChange", string.Format("changeBackgroundColor(this,'{0}');", textboxID));
ddlFont.Attributes.Add("OnChange", string.Format("changeTextColor(this,'{0}');", textboxID));
}
}
//control how the field is rendered in display mode, doesn't overide list view display which is controlled
//by the DisplayPattern in the fldtypes xml file

protected
override void RenderFieldForDisplay(HtmlTextWriter output)
{
StringBuilder sbldr = new StringBuilder();
sbldr.Append("
Sample Text
"
);
output.Write(sbldr.ToString());
}
}
}
. . .

I've commented the code so you can see what's going on so i'm not going to go into more detail here.  

Compile your class library & install it in the GAC Now you can create the ascx file you'll need

ControlTemplates_SPColorsPicker.ascx

Code CopyHideScrollFull
<%@ Control Language="C#" Debug="true" %>
<%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="SharePoint" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
Namespace="Microsoft.SharePoint.WebControls" %>
<SharePoint:RenderingTemplate ID="ColorsPicker" runat="server">
<Template>
<table>
<tr>
<td class="ms-formlabel">
Background Color</td>
<td>
<asp:DropDownList ID="ddlBackground" Width="200px" runat="server">
</
asp:DropDownList></td>
</tr>
<
tr>
<td class="ms-formlabel">
Text Color</td>
<td>
<asp:DropDownList ID="ddlFont" Width="200px" runat="server">
</
asp:DropDownList></td>
</tr>
</table>
<
br />
<
asp:TextBox ID="tbSampleText" runat="server" Font-Bold="True" ReadOnly="True">SAMPLE TEXT</asp:TextBox>
</Template>
</SharePoint:RenderingTemplate>
. . .

Then copy the ascx file to C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\CONTROLTEMPLATES

Open your class library using Lutz Roeder's Reflector to get hold of the assembly name which you'll need in the next file you need to create

fldtypes_SPColorsPicker.xml

Code CopyHideScrollFull
xml version="1.0" encoding="utf-8" ?>
<
FieldTypes>
<FieldType>
<Field Name="TypeName">ColorsField>
<
Field Name="ParentType">MultiColumnField>
<
Field Name="TypeDisplayName">Colors PickerField>
<
Field Name="TypeShortDescription">Pick Background and Font ColorsField>
<
Field Name="UserCreatable">TRUEField>
<
Field Name="ShowInListCreate">TRUEField>
<
Field Name="ShowInDocumentLibraryCreate">TRUEField>
<
Field Name="ShowInColumnTemplateCreate">TRUEField>
<
Field Name="FieldTypeClass">SPColorsPicker.SPColorsPickerField, SPColorsPicker, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3a4554e68e310c34Field>
<
RenderPattern Name="DisplayPattern">
<Switch>
<Expr>
<Column/>
Expr>
<
Case Value="">
Case>
<
Default>
<HTML>
0" HTMLEncode="TRUE"/>
<
HTML>; background-color: ]]>HTML>
<
Column SubColumnNumber="1" HTMLEncode="TRUE"/>
<
HTML>">Sample Text
]]>HTML>
Default>
Switch>
RenderPattern>
FieldType>
FieldTypes>
. . .

Replace the value for FieldTypeClass with your assembly name then this file needs to be copied into C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\XML

Now all you need to do is either recycle the application pool or do an IISReset to have this new field type available to your SharePoint Lists

Well I've run out of time to show you how to use the value from within SharePoint designer (I'm sure blogging this took longer than actually creating the field) but I'll post a new article on that very soon.

posted on Saturday, March 29, 2008 12:34 PM

Feedback

# re: SharePoint/MOSS Color Picker Custom Field 4/10/2008 3:59 AM Vangi
Hi Andy,

Very good post. It's very helpfull.

I have an question. How you change background and font color of calendar events? What exactly mean "Custom calendar views using the field values through code"? Can you show some code?


# re: SharePoint/MOSS Color Picker Custom Field 4/10/2008 1:20 PM Skullcrusher
Hi Vangi

Unfortunately I'm not at liberty to show how I've done the color coding for calendar events otherwise i would have.

I can however give you some pointers. You basically need to create your own classes that inherit from the MonthlyCalendarView, WeeklyCalendarView and DailyCalendarView that SharePoint provides and override some methods, then modify the default template within SharePoint to use your classes instead.

Sorry I can't divulge more info.

Andy

# re: SharePoint/MOSS Color Picker Custom Field 4/15/2008 1:53 AM Vangi
Hi Andy,

I read a lot of posts about this and I need from some right point. Thanks for give me a hint.

# re: SharePoint/MOSS Color Picker Custom Field 6/30/2008 9:58 AM Steve
Hi Andy,
nice post, its been a great help.

One thing i am struggling with, writing my own custom field is getting the value to display in the "View Item" mode and on a published page (works fine on a page layout in edit mode).
Also, it works fine in list view...seems weird, I'm sure I'm missing something! I cant seem to filter on the column using the CQWP and I'm sure its linked??

Any ideas would be a great help
Thx
Steve

# re: SharePoint/MOSS Color Picker Custom Field 7/2/2008 10:37 AM Skullcrusher
Hi Steve

Glad you found it usefull

Without seeing your code it's hard to say why it's not working in View Item mode, are you overridding RenderFieldForDisplay?

Andy

# SharePoint Kaffeetasse #82 7/3/2008 12:41 AM Mirrored Blogs
Anpassung SharePoint/MOSS Color Picker Custom Field How to set SharePoint People Picker default value

# re: SharePoint/MOSS Color Picker Custom Field 7/24/2008 12:25 AM Prashant Ganesh
The article is really a very good one. Well presented!!

But please note, the XML for fldtypes_SPColorsPicker.xml specified in the Code is displayed in a malformed way.

Please do correct it and post the corrected xml.

# re: SharePoint/MOSS Color Picker Custom Field 7/24/2008 2:55 AM Prashant Ganesh
Here is the Well Formed XML



<?xml version="1.0" encoding="utf-8"?>
<FieldTypes>
<FieldType>
<Field Name="TypeName">Colors</Field>
<Field Name="ParentType">MultiColumn</Field>
<Field Name="TypeDisplayName">Colors Picker</Field>
<Field Name="TypeShortDescription">Pick Background and Font Colors</Field>
<Field Name="UserCreatable">TRUE</Field>
<Field Name="ShowInListCreate">TRUE</Field>
<Field Name="ShowInDocumentLibraryCreate">TRUE</Field>
<Field Name="ShowInColumnTemplateCreate">TRUE</Field>
<Field Name="FieldTypeClass">SPColorsPicker.SPColorsPickerField, SPColorsPicker, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3a4554e68e310c34</Field>
<RenderPattern Name="DisplayPattern">
<Switch>
<Expr>
<Column/>
</Expr>
<Case Value="">
</Case>
<Default>
<HTML>
<![CDATA[<div style="color:]]>
</HTML>
<Column SubColumnNumber="0" HTMLEncode="TRUE"/>
<HTML>
<![CDATA[;background-color:]]>
</HTML>
<Column SubColumnNumber="1" HTMLEncode="TRUE"/>
<HTML>
<![CDATA[;">Sample Text</div>]]>
</HTML>
</Default>
</Switch>
</RenderPattern>
</FieldType>
</FieldTypes>



# re: SharePoint/MOSS Color Picker Custom Field 5/12/2009 9:22 PM Mansour
Hi Andy,

Thank you for the good post; it is really helpful.

I am facing this issue:
""The name 'SecurityAction' does not exist in the current context""@ SPColorsPickerField.cs

any suggestions



Post Feedback

Title:
Name:
Url:
Comments: 
Protected by Clearscreen.SharpHIPEnter the code you see: