Thursday, November 19, 2009

Syntax Highlighter

I'd like to send a shout out & much thanks to Nilesh Thakkar, a software engineer at SIHL in India for recommending I introduce Syntax Highlighter into this blog.  It provides a super simple way to display source code to fellow developers.  You'll see it used in all future posts.

Incidentally, for anyone else writing a blog on Blogger, Matthew Ball has provided a step-by-step explanation of how to add Syntax Highlighter.

Thank you, Nilesh!!

Wednesday, November 18, 2009

Encoding & Decoding Bit-Sums For a CheckBoxList

Have you ever had occasion where you need to allow users to select one or more items in a list? With ASP.Net a good UI control to do that with is the CheckBoxList. Here's a pair of examples:



Then the question arises, how do you store their selections?  If the potential list is quite long then you're probably going to want to use a CDF string of the values you've assigned to each list item - example: "2,3,11,17,34"

But for smaller, more finite lists a good way to go is with bit-encoded sums.  You assign each list item a base-2 value, such as:
  • Item A    2^0 = 1
  • Item B    2^1 = 2
  • Item C    2^2 = 4
  • Item D    2^3 = 8
In this way, when the user has finished their selection, you can add up the associated values, store that sum, and then decode it later when you return to the page again.  Thus for the aforementioned example, if the user selected A, C, & D, the sum would be: 1 + 4 + 8 = 13.

Encoding the values is very straightforward.  Here's a little algorithm that does the job:
int newSum = 0;
    foreach (ListItem item in checkBoxList.Items)
    {
      if (item.Selected)
        newSum += Convert.ToInt32(item.Value);
    }

Decoding though is somewhat trickier.  I imagine there are many possible approaches.  Here's a method I created to do the job:
private void SelectCblItems(CheckBoxList cbl, int sum)
  {
    // Determine the largest Base-2 Power that comprises sum
    int maxPower = (int)Math.Log(sum, 2);
    for (int pow = maxPower; pow >= 0; pow--)
    {
      int partSum = (int)Math.Pow(2, pow);
      if (partSum <= sum)
      {
        ListItem listItem = cbl.Items.FindByValue(partSum.ToString());
        if (listItem != null)
          listItem.Selected = true;

        sum -= partSum;
      }
    }
  }