Silverlight 2, Html DOM Interoperability ( 2 )

Following on from this post, I changed the library code that I was using a little to make the job of creating HTML ( specifically in my case a table ) in Silverlight 2 easier again.

If I want to get hold of a div called myDiv and create a table within it then I can do ( as an example );

      HtmlElement el = HtmlPage.Document.GetElementById("myDiv");

      el.Add(
        new HElement(HElementType.table,
          new HElement(HElementType.tbody,
            new HElement(HElementType.tr,
              HElement.Replicate(HElementType.th, "Number", "Squared", "Cubed")),
            from i in Enumerable.Range(1, 10)
            select new HElement(HElementType.tr,
              HElement.Replicate(HElementType.td, i.ToString(), (i * i).ToString(), (i * i * i).ToString()),
              new HElement(HElementType.td,
                new HElement(HElementType.input,
                  new HAttribute(HAttributeType.type, "button"),
                  new HAttribute(HAttributeType.value, "click"),
                  new HEventHandler(HEventType.onclick,
                    (s, a) => MessageBox.Show(string.Format("You click on row number {0}", i)))))))));

I changed the supporting classes around a little – here they are;

public enum HElementType
{
  html,
  body,
  table,
  tbody,
  tr,
  td,
  th,
  input
  // etc...
}

public enum HEventType
{
  onclick
  // etc...
}

public enum HStyleType
{
  width,
  height
  // etc...
}

public enum HAttributeType
{
  type,
  value,
  innerText
  // etc...
}

internal static class Utility
{
  internal static string EnumToString<T>(object enumValue)
  {
    return (Enum.GetName(typeof(T), enumValue));
  }
}

public static class HtmlElementExtensions
{
  public static void Add(this HtmlElement parent, IEnumerable<HElement> elements)
  {
    foreach (HElement item in elements)
    {
      parent.AppendChild(item);
    }
  }
  public static void Add(this HtmlElement parent, params HElement[] elements)
  {
    foreach (HElement item in elements)
    {
      parent.AppendChild(item);
    }
  }
}
public class HAttribute
{
  public HAttribute(HAttributeType type, string value)
  {
    this.Type = type;
    this.Value = value;
  }
  public HAttributeType Type { get; set; }
  public string Value { get; set; }
}
public class HStyleAttribute
{
  public HStyleAttribute(HStyleType type, string value)
  {
    this.Type = type;
    this.Value = value;
  }
  public HStyleType Type { get; set; }
  public string Value { get; set; }
}
public class HEventHandler
{
  public HEventHandler(HEventType eventType, EventHandler<HtmlEventArgs> handler)
  {
    this.Type = eventType;
    this.Handler = handler;
  }
  public HEventType Type { get; set; }
  public EventHandler<HtmlEventArgs> Handler { get; set; }
}
public class HElement
{
  public static implicit operator HtmlElement(HElement el)
  {
    return (el.element);
  }
  public HElement(HElementType elementType, params object[] items)
  {
    element = HtmlPage.Document.CreateElement(Utility.EnumToString<HElementType>(elementType));
    AddItems(items);
  }
  public HElement(HElementType elementType, string value) : 
    this(elementType, new HAttribute(HAttributeType.innerText, value))
  {
  }
  public static IEnumerable<HElement> Replicate<T>(HElementType elementType,
    T parameter, params Func<T, string>[] actions)
  {
    foreach (Func<T, string> action in actions)
    {
      yield return new HElement(elementType, action(parameter));
    }
  }
  public static IEnumerable<HElement> Replicate(HElementType elementType,
    params string[] contents)
  {
    foreach (string content in contents)
    {
      yield return new HElement(elementType, content);
    }
  }
  void AddItems(object[] items)
  {
    foreach (object o in items)
    {
      if (o.GetType() == typeof(HElement))
      {
        AddSubElement((HElement)o);
      }
      else if (o.GetType() == typeof(HAttribute))
      {
        AddAttribute((HAttribute)o);
      }
      else if (o.GetType() == typeof(HStyleAttribute))
      {
        AddStyleAttribute((HStyleAttribute)o);
      }
      else if (o.GetType() == typeof(HEventHandler))
      {
        AddHandler((HEventHandler)o);
      }
      else
      {
        IEnumerable<HElement> elementList = o as IEnumerable<HElement>;

        if (elementList != null)
        {
          foreach (HElement el in elementList)
          {
            AddSubElement(el);
          }
        }
        else
        {
          IEnumerable<HAttribute> attrList = o as IEnumerable<HAttribute>;

          if (attrList != null)
          {
            foreach (HAttribute attr in attrList)
            {
              AddAttribute(attr);
            }
          }
          else
          {
            IEnumerable<HStyleAttribute> styleList = o as IEnumerable<HStyleAttribute>;

            if (styleList != null)
            {
              foreach (HStyleAttribute style in styleList)
              {
                AddStyleAttribute(style);
              }
            }
            else
            {
              throw new InvalidOperationException("Parameter type not supported");
            }
          }
        }
      }
    }
  }

  void AddHandler(HEventHandler handler)
  {
    element.AttachEvent(Utility.EnumToString<HEventType>(handler.Type), handler.Handler);
  }

  void AddStyleAttribute(HStyleAttribute styleAttribute)
  {
    element.SetStyleAttribute(Utility.EnumToString<HStyleType>(styleAttribute.Type), 
      styleAttribute.Value);
  }

  void AddAttribute(HAttribute attribute)
  {
    element.SetAttribute(Utility.EnumToString<HAttributeType>(attribute.Type), attribute.Value);
  }

  void AddSubElement(HElement subElement)
  {
    element.AppendChild(subElement);
  }
  HtmlElement element;
}