Wednesday, September 20, 2006
« Giving Blog Jet a Try... | Main | Getting DVD content onto an iPod 5.5g »

The Setup
I’ve run into an interesting problem using the DataList control. I have a datasource, an XML file, that has a series of ‘choices’ in it. The choices could be anything, products, a free item a person could choose when making a purchase, or even a color for a car. What I’m trying to do is have a datasource, bound to a repeater control that renders a series of elements as a group, while only allowing the user to choose one of them.

My data source calls them choices 1–9. There is some ancillary information that gets carried along with it, a small image, large image, text to descibe the element, and a code to identify it elsewhere. Microsoft is so good at getting us to adopt their controls in .NET, and for the most part, they’re decent.  But when you run into a limitation like I have, it’s frustrating.

The Problem
The data list control contains an item template and inside the item template resides an image, a radio button, and some text. It all renders fine, but the groupname property for the radio button does not work. I’ve even reverted back to an ‘input’ tag using HTML instead of .NET, and .NET is still mucking with the name. The problem becomes instead of being able to select one radio button, the user can select all nine!

Here is the HTML that is generated, you’ll quickly see why the radio buttons are not working:

<tr>

    <td>

        <img id="dtlListChoiceSelection__ctl0_imgSmallChoice" src="choice1Small.jpg"

        alt="Choice 1" border="0" /><br/>

        <input value="CHOICE1" name="dtlListChoiceSelection:_ctl0:CardChoice"

        id="dtlListChoiceSelection__ctl0_CardChoice" type="radio" />Choice 1

    </td>

    <td>

        <img id="dtlListChoiceSelection__ctl1_imgSmallChoice" src="choice2Small.jpg"

        alt="Choice 2" border="0" /><br/>

        <input value="CHOICE2" name="dtlListChoiceSelection:_ctl1:CardChoice"

        id="dtlListChoiceSelection__ctl1_CardChoice" type="radio" />Choice 2

    </td>

    <td>

        <img id="dtlListChoiceSelection__ctl2_imgSmallChoice" src="choice3Small.jpg"

        alt="Choice 3" border="0" /><br/>

        <input value="CHOICE3" name="dtlListChoiceSelection:_ctl2:CardChoice"

        id="dtlListChoiceSelection__ctl2_CardChoice" type="radio" />Choice 3

    </td>

</tr>

Here is a screenshot the bad radio buttons! Don't worry about the broken images, they are just there for fluff.

CropperCapture[14].Jpg

The repeater control is appending it’s container name, and incrementing it each time, so we’re not getting a single name for the radio button. I’ve tried the ASP.NET radio button as well, with the same result.

The Data
Here is all of the pieces, if you want to go away and test this on your own. I’ve tried several things, all of which I’ll explain at the end of the post. I have another way to solve the issue, but it just seems like I shouldn’t have to hassle like I have.

  • ASPX Page

    <asp:DataList RepeatDirection="Horizontal" RepeatColumns="3"
    id="dtlListChoiceSelection" runat="server">

        <ItemTemplate>

            <asp:Image id="imgSmallChoice" runat="server"
    AlternateText='<%# DataBinder.Eval(Container.DataItem, "ChoiceName")%>'
    ImageURL='<%# DataBinder.Eval(Container.DataItem, "SmallImage")%>' /><br/>

            <input type="radio" runat="server" name="CardChoice"
    value='<%# DataBinder.Eval(Container.DataItem, "ChoiceCode")%>'
    id="CardChoice"><%# DataBinder.Eval(Container.DataItem, "ChoiceName")%>

        </ItemTemplate>

    </asp:DataList>


  • ASPX CodeBehind

    public class testHarness : System.Web.UI.Page
    {
        protected System.Web.UI.WebControls.DataList dtlListChoiceSelection;
        private void Page_Load(object sender, System.EventArgs e)
        {
           
    BindChoiceSelectionList();
         }

               private void BindChoiceSelectionList()
               {
                     //find the datalist control
                    
DataList dtlListChoiceSelection = (DataList)Page.FindControl("dtlListChoiceSelection");

                     if (dtlListChoiceSelection != null)
                     {
                         //read the data from the xml file
                        
System.Data.DataSet ds = new System.Data.DataSet();
                         ds.ReadXml(Server.MapPath("ChoiceList.xml"));

                        //apply the dataset to the datalist control in the UI
                       
dtlListChoiceSelection.DataSource = ds.Tables[0].DefaultView;
                        dtlListChoiceSelection.DataBind();
                       }
                 }

  • XML Data File

    <?
    xml version="1.0" encoding="utf-8" ?>
    <ChoiceDefiniton>
      <Choice>
        <SmallImage>choice1Small.jpg</SmallImage>
       
    <LargeImage>choice1Large.jpg</LargeImage>
       
    <ChoiceName>Choice 1</ChoiceName>
       
    <ChoiceCode>CHOICE1</ChoiceCode>
      
    </Choice>
    <Choice>
        <SmallImage>choice2Small.jpg</SmallImage>
       
    <LargeImage>choice2Large.jpg</LargeImage>
       
    <ChoiceName>Choice 2</ChoiceName>
       
    <ChoiceCode>CHOICE2</ChoiceCode>
      
    </Choice>
      <Choice>
        <SmallImage>choice3Small.jpg</SmallImage>
       
    <LargeImage>choice3Large.jpg</LargeImage>
       
    <ChoiceName>Choice 3</ChoiceName>
       
    <ChoiceCode>CHOICE3</ChoiceCode>
      
    </Choice>
      <Choice>
        <SmallImage>choice4Small.jpg</SmallImage>
       
    <LargeImage>choice4Large.jpg</LargeImage>
       
    <ChoiceName>Choice 4</ChoiceName>
       
    <ChoiceCode>CHOICE4</ChoiceCode>
      
    </Choice>
      <Choice>
        <SmallImage>choice5Small.jpg</SmallImage>
       
    <LargeImage>choice5Large.jpg</LargeImage>
       
    <ChoiceName>Choice 5</ChoiceName>
       
    <ChoiceCode>CHOICE5</ChoiceCode>
      
    </Choice>
      <Choice>
        <SmallImage>choice6Small.jpg</SmallImage>
       
    <LargeImage>choice6Large.jpg</LargeImage>
       
    <ChoiceName>Choice 6</ChoiceName>
       
    <ChoiceCode>CHOICE6</ChoiceCode>
      
    </Choice>
      <Choice>
        <SmallImage>choice7Small.jpg</SmallImage>
       
    <LargeImage>choice7Large.jpg</LargeImage>
       
    <ChoiceName>Choice 7</ChoiceName>
       
    <ChoiceCode>CHOICE7</ChoiceCode>
      
    </Choice>
      <Choice>
        <SmallImage>choice8Small.jpg</SmallImage>
       
    <LargeImage>choice8Large.jpg</LargeImage>
       
    <ChoiceName>Choice 8</ChoiceName>
       
    <ChoiceCode>CHOICE8</ChoiceCode>
      
    </Choice>
      <Choice>
        <SmallImage>choice9Small.jpg</SmallImage>
       
    <LargeImage>choice9Large.jpg</LargeImage>
       
    <ChoiceName>Choice 9</ChoiceName>
       
    <ChoiceCode>CHOICE9</ChoiceCode>
      
    </Choice>


    What I’ve Tried
    I’ve tried using the asp:radio button inside my template, I’ve tried the HTML input type radio. I’ve tried to find the controls inside the page at PreRender, and rename them, that does not work either. I’ve tried finding the controls at PreRender, REMOVING them, and adding a STRING that is written inside a placeholder, and I get the same behaviour.

    Microsoft admits this to be a ‘known’ issue here. As I understand it, this is still a bug in .NET 2.0.

    There is a 3rd party control by MetaBuilders, but it’s not really an option for me, I can’t use an outside vendor’s controls for the work I’m doing. I’ve googled it, and searched all over and this seems to be the only solution.

    In Part II of this post, I’ll post how I solve this issue. So far, I’m not really satisfied with what I’ve come up with.