views:

361

answers:

1

Hi All,

I'm trying to add items to a listbox,combobox, radiolist using reflection. The code I have at the moment is as follows:

public static Control ConfigureControl(Control control, ControlConfig ctrlconf)
    {
        if (control is TextBox)
        {

            // ...
        }
        else
        {
            // get the properties of the control
            //

            Type controlType = control.GetType();

            PropertyInfo[] controlPropertiesArray = controlType.GetProperties();

            foreach (PropertyInfo controlProperty in controlPropertiesArray)
            {
                if (controlProperty.Name == "Items" && controlProperty.PropertyType == typeof(ListItemCollection))
                {
                    object instance = Activator.CreateInstance(controlProperty.PropertyType);
                    MethodInfo addMethod = controlProperty.PropertyType.GetMethod("Add", new Type[] { typeof(ListItem)} );
                    List<string> popValues = new List<string>(ctrlconf.PopulatedValues.Split(';'));
                    if (popValues.Count.Equals(0))
                    {
                        throw new ArgumentException("No values found for control");
                    }
                    else
                    {
                        foreach (string val in popValues)
                        {
                            addMethod.Invoke(instance, new object[] { new ListItem(val, val) });
                        }

                    }

                }
            }
        }

        return control;

    }

The code above populates the listitemcollection which I have instantiated using Activator.CreateInstance, however I'm not sure how to add it to the ListBox.

Any help would be great.

Thanks,

Peter

A: 

You don't need or want to instantiate the collection object: that's already done by the control. Instead, you need to get the existing collection object, then add to that:

if (controlProperty.Name == "Items" && controlProperty.PropertyType == typeof(ListItemCollection))
{
  object instance = controlProperty.GetValue(control, null);
  // ... now go on and add to the collection ...
}

However, as others have noted, this may not be the best way to approach the problem. Instead, consider implementing adapter or strategy for the various controls you want to support e.g. RadioButtonListItemAdder, ListControlItemAdder, etc., which all conform to a common interface. Each type of XxxItemAdder can implement its own strongly-typed code, suitable for the type of control it's responsible for adding items to. This might look something like the following:

public interface IItemAdder
{
  void AddItem(string value);
}

public class ListControlItemAdder : IItemAdder
{
  private readonly ListControl _listControl;

  public ListControlItemAdder(ListControl listControl)
  {
    _listControl = listControl;
  }

  public void AddItem(string value)
  {
    _listControl.Items.Add(value);  // or new ListItem(value, value) per your original code
  }
}

public class RadioButtonListItemAdder : IItemAdder
{
  // ...
  public void AddItem(string value)
  {
    // do whatever you have to do to add an item to a list of RadioButtons
  }
}

public static IItemAdder CreateItemAdderFor(Control control)
{
  if (control is ListControl)
    return new ListControlItemAdder((ListControl)control);
  else if (control is RadioButtonList)
    return new RadioButtonListItemAdder((RadioButtonList)control);
  // etc. to cover other cases
}

public static Control ConfigureControl(Control control, ...)
{
  // ... omitting code that looks like your existing code ...
  IItemAdder itemAdder = CreateItemAdderFor(control);
  foreach (string val in popValues)
    itemAdder.AddItem(val);
}

This is a really untidy implementation but hopefully gives you the idea of how you can separate out each of the individual control-specific implementations into small, nicely separated classes.

itowlson
Thanks itowlson - the code snippet did the trick! I dont suppose you would provide some simple code illustrating the adapter/strategy pattern. Many thanks once again for the fix.
Peter
Peter: Updated the answer to include *rudimentary* example code for breaking out the control-specific Add logic into adapters/strategies.
itowlson
Thanks itowlson - much appreciated.
Peter