views:

56

answers:

1

Is it possible to define a control to have non-specified set of attributes? For instance:

<MyPrefix:MyControl SomeAttribute="SomeValue" runat="server"/>

I don't want to define a property on the control class beforehand for "SomeAttribute." I'd really just like a HashTable or some other construct like this:

"SomeAttribute" => "SomeValue"

So this control can be used in many places with attributes that are essentially made up at runtime.

I'm wonder if there's some parsing method I can override which iterates through the attributes at parse time. I can:

  1. Look for a property with the name and set it
  2. If I don't find such a property, put the attribute name and value into a HashTable

Possible?

+4  A: 

You want to use the IAttributeAccessor interface.

Defines methods used by ASP.NET server controls to provide programmatic access to any attribute declared in the opening tag of a server control.

Example control:

using System;
using System.Collections.Generic;
using System.Web.UI;

namespace App_Code.Controls {
    public class OutputAttributesControl : Control, IAttributeAccessor {
        private readonly IDictionary<String, String> _attributes = new Dictionary<String, String>();

        protected override void Render(HtmlTextWriter writer) {
            writer.Write("Attributes:<br/>");
            if (_attributes.Count > 0) {
                foreach (var pair in _attributes) {
                    writer.Write("{0} = {1} <br/>", pair.Key, pair.Value);
                }
            } else {
                writer.Write("(None)");
            }
        }

        public String GetAttribute(String key) {
            return _attributes[key];
        }

        public void SetAttribute(String key, String value) {
            _attributes[key] = value;
        }
    }
}

Invocation:

<AppCode:OutputAttributesControl runat="server" attr="value" />

Output:

Attributes:
attr = value

Caveats:

It seems that SetAttribute is only called on attributes that can not be resolved normally. This means you'll not see the id- or the runat-attribute in your code. Assigned properties (attr="<%= DateTime.Now %>") show up as an empty string. Databound properties does not show up at all in design mode, but works in normal mode (assuming that someone called DataBind, as usual).

Simon Svensson
The problem is that parsing the control throws an error because there are attributes that don't map to properties.
Deane
Deane, that's not the behavior I'm seeing. I'll edit my post to show a control that handles everything thrown at it.
Simon Svensson
This worked perfectly in the end. If there is a matching property for an attribute, it assigns the value to the property. Otherwise, it calls SetAttribute and you can do anything you like in there.
Deane