Tuesday, December 15, 2009

The power of parameterContainer and ITemplate

Ok. Really trying to get back into blogging. Instead of always doing something complex, try to do something simple.

In this case. I want to discuss an issue I was working with R.A.D. ComboBox this week.

I'm continuing work on the YakShaver. Working on a portion of the UI in which case I use logical groups to divide out customers from projects. These groups contain a very small number of elements, anywhere from 1-5. Picture a tree structure such that

-Customer 1

- Project 1

- Project 2

- Project 3

-Customer 2

- And So on...

One of the great things about Telerik RAD ComboBox is the ability to have separator items, to give the user an easier view of logical groupings. This used to require a lot of in depth work between css, javascript, but now I simply drag a control on a page, click a few things and I'm done with it and everything looks pretty. RadComboBox easily allows me to set the text of the separator item or just leave it blank to create a line.

It also allows us to be more creative by using the to add all sorts of pizazz to our combo box improving the user experience; which was exactly what I intended to do. In my case, I was turning the drop down into a checkbox that I would validate later.

Hence came my problem.

The item template is invoked for every RadItem that exists, regardless of if its a separator or not. Having a simple table to handle our structure doesn't work. In my case what happened was every combo item would render with a checkbox, including my separator items. I wanted to add some conditional logic that says "If this is a separator item, then display this, else this."

Typically I would not put any sort of server side code in the UI, but this seemed to be one of the instances that it made the most sense. I wanted easy access to the the item being bound (the RadComboBoxItem) to tell if it was a separator. With no good way from what I could find with a declarative syntax, I thought about how I could do it conditionally inside item template.

Problem, how do I access the item? Answer: parameterContainer.

parameterContainer is of type System.Web.UI.Control that represents the item being injected into the template. In our case, it was the RadComboBoxItem. With a simple cast, I can access all the properties and methods in the aspx and get type safely (plus intellisense!).

I can use the standard <% %> syntax and therefore not have to have a dependency of HTML within the code behind. Here is an example.

   1:                  <telerik:RadComboBox runat="server" ID="rcbComponentDeploySites" OnLoad="cmb_Load">

   2:                              <ItemTemplate>

   3:                                  <% if (!(parameterContainer as RadComboBoxItem).IsSeparator)

   4:                                     {

   5:                                  %>

   6:                                  <table border="0">

   7:                                      <tr>

   8:                                          <td>

   9:                                              <asp:CheckBox runat="server" ID="chkDeployToSite" />

  10:                                          </td>

  11:                                          <td>

  12:                                              <%# DataBinder.Eval(Container, "Attributes['DisplayName']") %>

  13:                                              (<%# DataBinder.Eval(Container, "Text") %>)

  14:                                          </td>

  15:                                      </tr>

  16:                                  </table>

  17:                                  <%                      

  18:                                      }

  19:                                     else

  20:                                     {

  21:                                  %>

  22:                                  <table border="0">

  23:                                      <tr>

  24:                                          <td style="border-bottom: 1px dotted black;">

  25:                                              <%# DataBinder.Eval(Container, "Attributes['DisplayName']") %>

  26:                                              (<%# DataBinder.Eval(Container, "Text") %>)

  27:                                          </td>

  28:                                      </tr>

  29:                                  </table>

  30:                                  <%

  31:                                      }

  32:                                  %>

  33:                              </ItemTemplate>

  34:                              <Items>

  35:                                  <telerik:RadComboBoxItem runat="server" IsSeparator="true" Text="Customer 1 Sites" DisplayName="Customer 1 Sites" />

  36:                                  <telerik:RadComboBoxItem runat="server" Text="Customer Site 1" />

  37:                                  <telerik:RadComboBoxItem runat="server" Text="Customer Site 2" />

  38:                                  <telerik:RadComboBoxItem runat="server" IsSeparator="true" Text="Customer 2 Sites" DisplayName="Customer 2 Sites" />

  39:                                  <telerik:RadComboBoxItem runat="server" Text="Customer Site 1" />

  40:                                  <telerik:RadComboBoxItem runat="server" Text="Customer Site 2" />

  41:                              </Items>

  42:                          </telerik:RadComboBox>

This should be true of anything that implements ITemplate. It gives a great deal of flexibility to the UI and still allows for type safe programming.