EPiServer  /  CMS February 26, 2013

Enum properties with EPiServer

Make editors and developers alike happy with properties of custom enum types in EPiServer 7!

As developers we often need some sort of decision from editors where they should be able to choose from a limited number of options. There are ways of accomplishing that out-of-the-box by using drop down list properties or categories. None of them are very developer friendly though.

What I’d like is to create an enum and let editors choose from one of its values.

For instance, imagine that we have the two following enums:

public enum Decision
{
    Automatic = 0,
    No = 1,
    Yes = 2
}

public enum Priority
{
    VeryLow = 1,
    Low = 2,
    Medium = 0,
    High = 3,
    VeryHigh = 4
}

Wouldn’t it be nice if we could easily add properties of those types and let editors work with them using drop downs? Like this:

enums_as_dropdowns

Luckily we can.

There are two magic ingredients – a selection factory and an editor descriptor.

The selection factory

Selection factories are classes implementing ISelectionFactory. They can be used as a sort of data source for properties that are edited using EPiServer’s SelectionEditor.

To avoid having to create separate selection factories for each enum type we can create a generic one:

public class EnumSelectionFactory<TEnum> : ISelectionFactory
{
    public IEnumerable<ISelectItem> GetSelections(
        ExtendedMetadata metadata)
    {
        var values = Enum.GetValues(typeof (TEnum));
        foreach (var value in values)
        {
            yield return new SelectItem
                {
                    Text = GetValueName(value),
                    Value = value
                };
        }
    }

    private string GetValueName(object value)
    {
        var staticName = Enum.GetName(typeof (TEnum), value);

        string localizationPath = string.Format(
            "/property/enum/{0}/{1}",
            typeof (TEnum).Name.ToLowerInvariant(),
            staticName.ToLowerInvariant());

        string localizedName;
        if (LocalizationService.Current.TryGetString(
            localizationPath, 
            out localizedName))
        {
            return localizedName;
        }

        return staticName;
    }
}

Yes, you’re allowed to just copy and paste that code.

The editor descriptor

To allow editors to work with properties of enum types using drop downs we’ll an editor descriptor as the magic clue that connects each property to the selection factory.

public class EnumEditorDescriptor<TEnum> : EditorDescriptor
{
    public override void ModifyMetadata(
        ExtendedMetadata metadata, 
        IEnumerable<Attribute> attributes)
    {
        SelectionFactoryType = typeof(EnumSelectionFactory<TEnum>);

        ClientEditingClass = 
            "epi.cms.contentediting.editors.SelectionEditor";

        base.ModifyMetadata(metadata, attributes);
    }
}

Creating properties

Now we can create properties in page and block types as enums. There’s two things we’ll need to add to each property though.

We need to tell EPiServer how to store the property’s value by mapping it to a type that it can deal with. We do that using a BackingType attribute.

Second, we need to hook up our properties to the editor descriptor with the enum type as type argument.

[BackingType(typeof(PropertyNumber))]
[EditorDescriptor(EditorDescriptorType = typeof(EnumEditorDescriptor<Decision>))]
public virtual Decision ShowTableOfContents { get; set; }

[BackingType(typeof(PropertyNumber))]
[EditorDescriptor(EditorDescriptorType = typeof(EnumEditorDescriptor<Priority>))]
public virtual Priority SearchPriority { get; set; }

That’s a bit more attributes than I’d like. Still, I think it’s a low price to pay considering the alternatives.

Localization

If you paid attention to the code for the selection factory you probably saw that we can localize the select items as well.

<property>
  <enum>
    <decision>
      <automatic>Automagiskt</automatic>
      <yes>Ja!</yes>
      <no>Näe</no>
    </decision>
  </enum>
</property>

localized_enum_property

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Joel Abrahamsson

Joel Abrahamsson

I'm a passionate web developer and systems architect living in Stockholm, Sweden. I work as CTO for a large media site and enjoy developing with all technologies, especially .NET, Node.js, and ElasticSearch. Read more

Comments

comments powered by Disqus

My book

Want a structured way to learn EPiServer 7 development? Check out my book on Leanpub!

More about EPiServer CMS