Home > .net 3.0, c#, LINQ > Crazy Way To Set Display Order From an Enum

Crazy Way To Set Display Order From an Enum

March 9, 2010

I’m sure someone has a better way to do this and I’m all ears; however, this seems to ‘work’ and performs well enough (YAGNI fully applied).

We have an Enum of our different “school levels”–elementary, middle, high schools, special schools, etc.  Since the Enum’s values correspond to the data values in our student system, their display/alphabetical orders do not match the common order (e.g. High School = 4, Middle School = 5).

I came up with a simple attribute that’s added to the Enum to “specify” display order and it’s worked like a champ for the past year or so.

[Description("Elementary")]
[DisplayOrder(1)]
Elementary = 2,

[Description("Middle")]
[DisplayOrder(2)]
Middle = 5,

Not at all fancy.

However useful it is at looping and providing context in code, what about using it for ordering OTHER “level” information from another source?  So far, I haven’t found a clean way.

The “Solution”?

Use the index of our already-ordered Enum list.  In this instance, our model’s SchoolLevel property matches the Description of the Enum.

            var levelsInOrder = Enum<level>.ToList();
            // AutoMapper mappings, etc.

            model.Data = data
                .OrderBy(x => levelsInOrder
                    .FindIndex(z => z.Description() == x.SchoolLevel));

Is it perfect? No, but it works. I could probably even refactor the Enum list and FindIndex call out for a bit more clarity.

        model.Data = data.OrderBy(x => x.GetDisplayOrder(x.SchoolLevel));

        ...

        private int GetDisplayOrder(string level)
        {
            return Enum<level>.ToList().FindIndex(x => x.Description() == level);
        }

Is there a better way?

Categories: .net 3.0, c#, LINQ Tags: , ,
  1. ivowiblo
    March 10, 2010 at 11:33 am

    You could always use a class:
    instead of
    public enum EducationLevel{
    [Description(“Elementary”)]
    [DisplayOrder(1)]
    Elementary = 2,

    [Description(“Middle”)]
    [DisplayOrder(2)]
    Middle = 5,
    }

    you could do:

    public class Educationlevel{
    public static readonly EducationLevel Elementary = new EducationLevel(“Elementary”, 2, 1);
    public static readonly EducationLevel Middle = new Middle (“Middle”, 4, 2);

    public string Description{get;private set;}
    public int Value{get;private set;}
    public int DisplayOrder{get;private set;}

    private EducationLevel( string description, int value, int displayOrder){
    Description = description;
    Value = value;
    DisplayOrder = displayOrder;
    }
    }

  2. May 6, 2010 at 4:41 pm

    I’m with ivowiblo, I think using a class is more flexible and easier to maintain. I modified his/her class to include a list of education levels:

    ———–
    public class EducationLevel
    {
    public string Description { get; private set; }
    public int Value { get; private set; }
    public int DisplayOrder { get; private set; }

    public static List EducationLevels = new List();

    private EducationLevel(string description, int value, int displayOrder)
    {
    Description = description;
    Value = value;
    DisplayOrder = displayOrder;
    EducationLevel.EducationLevels.Add(this);
    }

    public static readonly EducationLevel Elementary = new EducationLevel(“Elementary”, 2, 1);
    public static readonly EducationLevel Middle = new EducationLevel(“Middle”, 5, 2);
    public static readonly EducationLevel HighSchool = new EducationLevel(“HighSchool”, 4, 3);
    }

    Now you can access everything:
    ——-
    EducationLevel eLevel = EducationLevel.HighSchool;
    Console.WriteLine(“{0}, value = {1}, Order = {2}”, eLevel.Description, eLevel.Value, eLevel.DisplayOrder);
    Console.WriteLine(“—“);

    foreach (var el in EducationLevel.EducationLevels.OrderBy(el => el.DisplayOrder))
    {
    Console.WriteLine(“{0}, value = {1}, Order = {2}”, el.Description, el.Value, el.DisplayOrder);
    }
    Console.WriteLine(“—“);

    The only problem (which is solvable) here is that you can modify the list like this:
    ——-
    EducationLevel.EducationLevels[0] = EducationLevel.Middle;
    EducationLevel.EducationLevels[1] = EducationLevel.Middle;
    EducationLevel.EducationLevels[2] = EducationLevel.Middle;

    You can solve this problem by making the list private and providing a deep copy of the list to the caller.

  1. No trackbacks yet.
Comments are closed.
%d bloggers like this: