Sunday, December 19, 2010

Populating ListControls

I was reviewing some code that I had written some time ago and had every intension of going back and refactoring. The code in question looks like this:
Drop Down List Populator
  1. private void BuildLists() {
  2.    BuildReferenceDropDownList(ddlLocation, ReferenceType.Location);
  3.    BuildReferenceDropDownList(ddlBeltType, ReferenceType.BeltType);
  4.    BuildReferenceDropDownList(ddlBusinessUnit, ReferenceType.BusinessUnit);
  5.    BuildReferenceDropDownList(ddlAgency, ReferenceType.Agency);
  6.    BuildReferenceDropDownList(ddlOrganization, ReferenceType.Organization);
  7.  
  8.  }
  9.  
  10.  private void BuildReferenceDropDownList(DropDownList ddl, ReferenceType referenceType) {
  11.    List<Reference> refItems;
  12.    refItems = referenceAdapter.GetAllByType(referenceType);
  13.    foreach (Reference r in refItems) { ddl.Items.Add(new ListItem(r._shortAndLongName, r._referenceID.ToString())); }
  14.  
  15.    PrependDefaultDropDownListItem(ddl);
  16.  }
  17.  
  18.  //-------------------------------------------------------------------------
  19.  protected void PrependDefaultDropDownListItem(DropDownList ddl) {
  20.    ListItem li = new ListItem("-- Select --", "-1");
  21.    //li.Selected = true;
  22.    ddl.Items.Insert(0, li);
  23.  }
and I had another area in the code that looked like this:
Check Box List Populator
  1. private void populateWants() {
  2.    List<Reference> _refPAWant = new List<Reference>(); // Holds all PAs sought by user
  3.    _refPAWant = _paAdapter.GetAllByUserIDAndType(user._employeeID, ProfessionalAttributeObjective.Seek, _professionalAttributeType);
  4.  
  5.    buildCheckBoxList(cblGoalsWant, _refPAGoals);
  6.    populateCheckBoxList(cblGoalsWant, _refPAWant);
  7.  }
  8.  
  9.  
  10.  private void populateHas() {
  11.    List<Reference> _refPAHave = new List<Reference>(); // Holds all PAs possessed by user
  12.    _refPAHave = _paAdapter.GetAllByUserIDAndType(user._employeeID, ProfessionalAttributeObjective.Offer, _professionalAttributeType);
  13.  
  14.    buildCheckBoxList(cblGoalsHave, _refPAGoals);
  15.    populateCheckBoxList(cblGoalsHave, _refPAHave);
  16.  }
  17.  
  18.  
  19.  private void buildCheckBoxList(CheckBoxList cbl, List<Reference> refItems) {
  20.    foreach (Reference r in refItems) {
  21.      cbl.Items.Add(new ListItem(r._shortName, r._referenceID.ToString()));
  22.    }
  23.  }
  24.  
  25.  private void populateCheckBoxList(CheckBoxList cbl, List<Reference> refItems) {
  26.    foreach (Reference r in refItems) {
  27.      if (cbl.Items.FindByValue(r._referenceID.ToString()) != null) { cbl.Items.FindByValue(r._referenceID.ToString()).Selected = true; }
  28.    }
After looking through this code I realized that the private void BuildReferenceDropDownList – from the drop down and the private void buildCheckBoxList – from the Check Box were almost identical, the only difference between the two was the argument being pasted in, the dropdown was receiving the dropdown control and the checkbox was receiving the checkbox control. Another minor difference was that the Dropdown had an added item at the beginning of the selection.
Once the gerbil in my head started running and I realized that both of this object derive from the ListControl object(ButtonList, ListBox, & RadioButtonList also derive from ListContol), it made my job of refactoring this a lot easier. I created a single method that accepts a ListControl and the Generic List in as arguments , then returns a ListControl back to the control that called it:
List Control Populator Method
  1. using System.Collections.Generic;
  2. using System.Web.UI.WebControls;
  3. using Models;
  4.  
  5. namespace GenericNamespace
  6. {
  7.     public class ListControlPopulator
  8.     {
  9.         public ListControl PopulateList(ListControl dll, List<Reference> reference)
  10.         {
  11.             if (dll.GetType().Equals(typeof(DropDownList)))
  12.                 dll.Items.Add(new ListItem("-- Select --", "-1"));
  13.  
  14.             foreach (Reference r in reference)
  15.             {
  16.                 dll.Items.Add(new ListItem(r._shortAndLongName, r._referenceID.ToString()));
  17.             }
  18.  
  19.             return dll;
  20.         }
  21.     }
  22. }
Look at line 11, here I am checking the type of the listcontrol being past into the method and if it is a dropdownlist I am able to add the line to the Drop Down.
To call this method we made the code look for the dropdown like this:
Dropdown List Control - Now
  1. ListControlPopulator ddl = new ListControlPopulator();
  2. private void BuildLists()
  3. {
  4.     ddlLocation     = (DropDownList)ddl.PopulateList((ListControl)ddlLocation, referenceAdapter.GetAllByType(ReferenceType.Location));
  5.     ddlBeltType     = (DropDownList)ddl.PopulateList((ListControl)ddlBeltType, referenceAdapter.GetAllByType(ReferenceType.BeltType));
  6.     ddlBusinessUnit = (DropDownList)ddl.PopulateList((ListControl)ddlBusinessUnit, referenceAdapter.GetAllByType(ReferenceType.BusinessUnit));
  7.     ddlAgency       = (DropDownList)ddl.PopulateList((ListControl)ddlAgency, referenceAdapter.GetAllByType(ReferenceType.Agency));
  8.     ddlOrganization = (DropDownList)ddl.PopulateList((ListControl)ddlOrganization, referenceAdapter.GetAllByType(ReferenceType.Organization));
  9. }

And the Checkbox Control look like this:
Checkbox List Control - Now
  1. ListControlPopulator ddl = new ListControlPopulator();
  2.     private void populateWants()
  3.     {
  4.       List<Reference> _refPAWant = new List<Reference>(); // Holds all PAs sought by user
  5.       _refPAWant = _paAdapter.GetAllByUserIDAndType(user._employeeID, ProfessionalAttributeObjective.Seek, _professionalAttributeType);
  6.       cblGoalsWant = (CheckBoxList)ddl.PopulateList((ListControl)cblGoalsWant, _refPAGoals);
  7.       populateCheckBoxList(cblGoalsWant, _refPAWant);
  8.     }
What made this easier was that fact that all of the look ups were centralized in one table, which means that List<T> is a single business object. I am going to research and see if I can accept any List<T>. So if you happen to have a single Business Object that is populating all of our ListControls consider using this. Of cource if you have a better way, please share it I am always looking for an easier way of doing something.

No comments: