Custom Item Generator: Customization

  • Gabe Boys
  • March 2, 2011

In my last posts, I introduced the Velir Custom Item Generator (CIG) and gave a simple example how for it can be installed and used. This post discusses the two most common ways the CIG can be customized; which are through the mapping of Sitecore fields to custom field classes, and through the adjusting of code templates.

One advantage of using the CIG is that it keeps things in a common sense structure based on the template folder structure. In most cases, it is not recommended to change how the namespace and file paths for the CIG classes are generated. If you change this then you are losing an inherent advantage of using the tool.

Supporting Custom Sitecore Fields

A common type of customization that is needed when using the CIG would be updating the tool to work with solution specific field types. These may be fields that have been written specifically for your solution or community provided fields such as the ones found here:

http://trac.sitecore.net/FieldTypes/

The mapping of field names to the classes that wrap them is done in the following file:

~/App_Config/Include/CustomItem.config

CIG Provided Class Overview

An important aspect of the custom item pattern is wrapping access to template fields. The CIG accomplishes this by using a custom class to handle access to a field’s properties and values. For each kind of field we want to provide the following:

  • Raw Field Value – The underlying textual value of the field.
  • Rendered Field Value – The value of the field after being processed by the field renderer.
  • Sitecore Field Class – The underlying Sitecore field class which may be needed to access extra information about the field.

All of the CIG provided field classes inherit from CustomItemGenerator.Fields.BaseCustomField. This class provides the basic field access mentioned above (raw, rendered, Sitecore field class.) A good example of a custom field class is the CustomItemGenerator.Fields.SimpleTypes.CustomCheckboxField class. In addition to the base calls provided by the BaseCustomField class the CustomCheckboxField class also has a convenience property for determining if the checkbox is checked. This property allows easy access to the most needed value from a check box field (i.e. if the checkbox is checked.) 

The intention of these field wrapping classes is to provide extra methods and properties which make it easier to work with that specific type of field. While you can often accomplish this using the Sitecore provided field class, this requires more specific knowledge of the API. An advantage of using a tool like the CIG is to abstract the developers from the Sitecore API so they can competently accomplish tasks without having to know every necessary underlying API call.

Creating Custom Field Mapping

The most common situation where you would need to add a custom mapping for the CIG is when you are using a custom field in your Sitecore solution. There are two steps that need to be taken in order to add a new type of field class to the CIG:

  1. Create the field class needed for wrapping the new field
  2. Add a mapping to the CustomItem.config file to map the field name to the newly created class

All of the Sitecore provided field classes, which can be found in the Sitecore.Data.Fields namespace, inherit from the CustomField class. The field classes provided with the CIG are assuming that all fields they are wrapping also derive from this class. This is fine for the Sitecore provided fields, but it is not uncommon for community or custom fields to not inherit from this class. If this is the case then we need to slightly change how we generate the wrapping class.

Regardless of how the field is implemented we will need to add a mapping from the field name to the newly created class. This mapping is added to the CustomItem.config file in the FieldMappings configuration section by using the following format:

<FieldMapping fieldType="[Sitecore Field Name]">
[Custom Field Class Name]
</FieldMapping>

Fields based on CustomField

Creating a field wrapping class for a field that inherits from CustomField is the most straightforward to implement. As mentioned above, all of the Sitecore provided field classes are derived from this class. For an example of how to do this see the code for any of the CIG provided field classes, such as:

CustomCheckboxField Code

There is not much to explain here, by inheriting from the BaseCustomField class we get the base methods and properties that we expect. Then in the created class we can add any additional methods or properties that our custom field may need.

Fields not based on CustomField

If the custom field is not based on the CustomField class then the custom field class creation process will be different. As an example here I am going to use the Slider field which can be found here http://trac.sitecore.net/FieldTypes/wiki/Slider, this field does not inherit from the CustomField class.

What we need to do in this case is create a class based on one of the generic text field classes and then change what the common sense return value is going to be. In this case the slider stores a float value which represents the selected slider value of the field. To generalize this I am going to create a custom field class that will try to parse and return the float value of the field. The code would look something like this:

public partial class CustomSliderField : BaseCustomField<TextField> { 

public CustomSliderField(Item item, TextField field)
: base(item, field) { } 

public float SliderValue { get { //Parse field float value } } 

}

Updating the Code Generation Templates

Code generation in the CIG is done using NVelocity, the template engine that comes with Sitecore. By using a template engine, instead of outputting the code programmatically, it gives us more flexibility to adjust the outputted code without having to dig into the code. The main code template for the base custom item classes can be found here:

~sitecore modulesShellCustomItemGeneratorNvelocity TemplatesCustomItem.base.vm

A common addition to this file would be to add extra “using” statements to the top of generated class files. If we create custom field classes which all reside in the namespace, Example.Project.CustomFields, for example, then when we create custom items for templates that use these custom fields we are going to have to add a using to each created class file.  If you are creating a lot of custom items, then this process can be tedious.

Making this addition is simple; all we would have to do is add the following to the top of the CustomItem.base.vm file:

using Example.Project.CustomFields;

Customizing Namespace and File Path Providers

In most cases, changing this behavior is not recommended. You can override how the namespaces and file paths for the generated classes are built by replacing the configuration settings in the CustomItem.config file. To override these settings you would create classes that implement::

CustomItemGenerator.Interfaces.ICustomItemNamespaceProvider

or

CustomItemGenerator.Interfaces.ICustomItemFolderPathProvider

Decipher which option is best to use depending on what is being overridden. To see how the default providers work see one of the following:

CustomItemGenerator.Providers.TemplatePathFilePathProvider
CustomItemGenerator.Providers.TemplatePathNameSpaceProvider