Mittwoch, 7. Juli 2010

Create a custom field-type - ein benutzerdefiniertes Field-type erstellen

Wie man ein benutzerdefinierten FieldType erstellt.
Es kommt vor, dass man beim Erstellen einer Spalte in einer Liste gerne einen FieldType hätte, der benutzerdefiniert ist, weil man vielleicht Daten separat speichern will oder eine Interaktion durchführen. Hierzu kann man einen Feldtyp benutzerdefinieren.
Als erstes ein leeres Sharepointprojekt in Visual Studio 2010 erstellen. Dann die folgenden Punkte durchgehen:

How to create a custom field-type.
Sometimes you might want to use a field-type when creating a new column in a list. This can be useful, when wanting to save data in a different place or interact with the data inserted. Therefore you can create a custom field-type.
First create an empty Sharepoint-project in Visual Studio 2010 and then follow this instruction:

1. Mappen Sie folgende Sharepoint Ordner, indem man das Projekt mit rechter Maustaste -> Hinzufügen -> Sharepointverzeichnis mappen anklickt.
Map the following sharepoint-directories, in clicking the project with the right mouse-key -> Add -> Sharepoint Mapped Folder
map the sharepoint folders

Grossansicht anzeigen - Show large image


2. Bitte folgende Verezichnisse mappen: Template\Controltemplates, Template\XML, Template\Layouts\XSL
Please map the following folders: : Template\Controltemplates, Template\XML, Template\Layouts\XSL

3. Fügen Sie Ihrem Projekt 3 Klassendateien hinzu: [Ihr Name].Field.cs, [Ihr Name].FieldControl.cs, [Ihr Name].ValidationRule.cs
Then add three class-files to your project: [Your name].Field.cs, [Your name].FieldControl.cs, [Your name].ValidationRule.cs

!!Hinweis: [Ihre Name].FieldControl.cs wird die Codebehinddatei Ihres Usercontrols!!
!!Hint: [Your name].FieldControl.cs will be the code-behind file of your user-control!!

4. Fügen Sie den mapped Verzeichnissen folgende Dateien hinzu, so dass zum Schluss Ihr Projekt wie folgt aussieht: [Ihr Name]FieldControl.ascx (CONTROLTEMPLATES), fldtypes_[Ihr Name].xml (XML), fldtypes_[Ihr Name].xsl (XSL)
Add the following files to your mapped folders, so your project will look like this: [Your name]FieldControl.ascx (CONTROLTEMPLATES), fldtypes_[Your name].xml (XML), fldtypes_[Your name].xsl (XSL)
sharepoint project

Grossansicht anzeigen - Show large image


5. Fügen Sie die Referenzen hinzu, welche in der Grafik angezeigt werden.
Add the references shown in the image.
references

Grossansicht anzeigen - Show large image



Verantwortlichkeiten:
Responsibilities:
- Wenn man Neu, Bearbeiten oder Anzeigen eines Listitems anklickt, erscheint ein Fenster. Zuständig für diese Anzeige ist die ascx Datei.
When clicking new, edit or display of a list-item, then a window opens. Responsible for the display style is the ascx file.
- Wie der Item in der Liste angezeigt wird, das regelt die xsl Datei.
How the item will be displayed in the list, that is handled through the xsl file.
- Die Eigenschaften, sowie die Bezeichnung links, neben dem ascx Inhalt, wird in der xml Datei bearbeitet.
The properties, and the name on the left side, next to the ascx content, will be defined in the xml file.
Hier eine Grafik zu der Erklärung:
Here you see an image to the explanation:
Overview diagram

Grossansicht anzeigen - Show large image



5. In der ascx Datei definieren Sie über die Rendering Templates die Darstellung in den verschiedenen Modi.
In the ascx file you define through the rendering-templates the different display variations in the different modes.
Ascx file

Grossansicht anzeigen - Show large image


6. Die folgenden Grafiken zeigen die Formatierung der XML und XSL Datei.
The following images show you the format of the xml and xsl file.
XML and XSL file

Grossansicht anzeigen - Show large image

XML and XSL file

Grossansicht anzeigen - Show large image


Hier ein Beispiel Code für die [Ihr Name].Field.cs.
Here is a sample code for the [Your name].Field.cs.

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

using System.Windows.Controls;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Security.Permissions;

namespace [Your namespace]
{
public class MyCustomField : SPField
{
//You have to use those constructors. Leave them like they are or extend with custom code if you need to.
public MyCustomField(SPFieldCollection fields, string fieldName)
: base(fields, fieldName)
{
}

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

//This method will call and start render the control. You can keep it this way.
public override BaseFieldControl FieldRenderingControl
{
[SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
get
{
//In case your control does have a different name, initialize it here
BaseFieldControl fieldControl = new MyCustomFieldControl();
fieldControl.FieldName = this.InternalName;
return fieldControl;
}
}

//This method validates the value. The validation-class will be initialized (MyCustomFieldValidationRule)
//That means you can leave everything, like it is, just be sure your correct validation-class is called
public override string GetValidatedString(object value)
{
if ((this.Required == true)
&&
((value == null)
||
((String)value == "")))
{
throw new SPFieldValidationException(this.Title
+ " must have a value.");
}
else
{
//Your custom validation class is supposed to be called here
MyCustomFieldValidationRule rule = new MyCustomFieldValidationRule();
ValidationResult result = rule.Validate(value, CultureInfo.InvariantCulture);

if (!result.IsValid)
{
throw new SPFieldValidationException((String)result.ErrorContent);
}
else
{
return base.GetValidatedString(value);
}
}
}
}
}



Hier ein Beispiel Code für die [Ihr Name].FieldControl.cs.
Here is a sample code for the [Your name].FieldControl.cs.

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;

using System.Runtime.InteropServices;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace [Your namespace]
{
public class MyCustomFieldControl : BaseFieldControl
{
protected global::System.Web.UI.WebControls.Label AdditionalInfoNew;
protected global::System.Web.UI.WebControls.TextBox TextFieldNew;
protected global::System.Web.UI.WebControls.Label AdditionalInfoEdit;
protected global::System.Web.UI.WebControls.TextBox TextFieldEdit;
protected global::System.Web.UI.WebControls.Label AdditionalInfoDisplay;
protected global::System.Web.UI.WebControls.Label DisplayText;

//This method initializes the correct rendering-template, depending on the mode.
protected override string DefaultTemplateName
{
get
{
if (this.ControlMode == SPControlMode.Display)
{
//This template will be called, if the mode is display
return this.DisplayTemplateName;
}
else if (this.ControlMode == SPControlMode.Edit)
{
//This template will be called, if the mode is edit
return "RenderingTemplateEdit";
}
else
{
//This template will be called, if the mode is new or invalid, you can also set one for each
return "RenderingTemplateNew";
}
}
}

//You need to override this template-name, otherwise there seems to be a default one and your web-controls won't be recognized in the
//CreateChildControls method and it will throw an exception. Tell explicit, which renderingtemplate to use for display.
public override string DisplayTemplateName
{
get
{
return "RenderingTemplateDisplay";
}
set
{
base.DisplayTemplateName = value;
}
}

//This method creates the child-controls and runs some major code.
protected override void CreateChildControls()
{
if (this.Field != null)
{
//Make sure inherited child controls are completely rendered.
base.CreateChildControls();

//Associate child controls in the .ascx file with the
//fields allocated by this control.
this.AdditionalInfoNew = (Label)TemplateContainer.FindControl("AdditionalInfoNew");
this.TextFieldNew = (TextBox)TemplateContainer.FindControl("TextFieldNew");
this.AdditionalInfoEdit = (Label)TemplateContainer.FindControl("AdditionalInfoEdit");
this.TextFieldEdit = (TextBox)TemplateContainer.FindControl("TextFieldEdit");
this.AdditionalInfoDisplay = (Label)TemplateContainer.FindControl("AdditionalInfoDisplay");
this.DisplayText = (Label)TemplateContainer.FindControl("DisplayText");

//This code runs if not display mode
if (this.ControlMode != SPControlMode.Display)
{
if (!this.Page.IsPostBack)
{
if (this.ControlMode == SPControlMode.New)
{
//The method 'GetCustomProperty' gets the value set, that depends on the property-schema field in the xml.
this.TextFieldNew.Text = (String)base.Field.GetCustomProperty("MyPropertyintheXML");
this.AdditionalInfoNew.Text = "You are in 'new' mode: ";
//!!!Take care to use the correct controls, otherwise there won't be anything visible!!!!!!
}

else if (this.ControlMode == SPControlMode.Edit)
{
//The method 'GetCustomProperty' gets the value set, that depends on the property-schema field in the xml.
this.TextFieldEdit.Text = (String)base.Field.GetCustomProperty("MyPropertyintheXML");
this.AdditionalInfoEdit.Text = "You are in 'edit' mode: ";
//!!!Take care to use the correct controls, otherwise there won't be anything visible!!!!!!
}
}

}
else
{
//Assign current value from database to the label control
if (!string.IsNullOrEmpty(this.ItemFieldValue.ToString()))
DisplayText.Text = (String)this.ItemFieldValue;
this.AdditionalInfoDisplay.Text = "You are in 'display' mode: ";
//!!!Take care to use the correct controls, otherwise there won't be anything visible!!!!!!
//!!!Exception? web-controls are not recognized? then check if the property is overriden: DisplayTemplateName !!!!!!
}
}
}

//The value object is the final value that will be stored in the list-column.
public override object Value
{
get
{
EnsureChildControls();
//Here you return the value, that finally will be written into the column value.
//Start custom code ************************************************************************

//End custom code **************************************************************************
return "[This is the column value]";
}
}

//The UpdateFieldValueInItem method stores the value in the database and runs code, that needs to be done before doing the update and finalizing the insert.
public override void UpdateFieldValueInItem()
{
Page.Validate();
if (Page.IsValid)
{
//Code that is supposed to be executed before everything is stored and the update is done.
//Start custom code ************************************************************************

//End custom code **************************************************************************
base.UpdateFieldValueInItem();
}
else
{
//Code that is supposed to be executed in case the page is not valid and the update failed.
}
}
}
}



Hier ein Beispiel Code für die [Ihr Name].ValidationRule.cs.
Here is a sample code for the [Your name].ValidationRule.cs.

namespace [Your namespace]
{
public class MyCustomFieldValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
//The overloaded value is the one you have to validate against.
//Start custom code ************************************************************************

//End custom code **************************************************************************
//Your custom code needs to return a ValidationResult like the one below. Set either true or false and an error-message
//in your code to return, depending on your validation.
return new ValidationResult(true, "Everything is OK.");
}
}
}

Keine Kommentare:

Kommentar veröffentlichen