PopupControl/RadioButtonList as DropDownList Alternative

My current employer uses a web based tool for project management.  The tool is visually appealing and provides users with a great web experience.  It's an ASP.NET application that relies heavily on ASP.NET AJAX.  One of the AJAX features I like is the use of a popup control for status/type selection (i.e. what state is this bug {Open, Closed, Pending Acceptance, ...}).  Most existing web and windows applications usually present this as a drop down list. 

Live Demo | Download

Obviously, there is nothing wrong with the drop down approach, but I thought I would create an example showing an alternative technique using the PopupControlExtender found in the AjaxControlToolkit along with the regular ASP.NET RadioButtonList control.  The main advantage the PopupControl/RadioButtonList approach has over the standard ASP.NET DropDownList is that it provides the developer with a finer grained control over the presentation.  Here are a couple of screen shots that show this alternative technique.  Because the RadioButtonList control exposes attributes for controlling the layout, it is easy to configure exactly how you want the control to render.  Also, because the PopupControl hides and shows a Panel, you can pretty much make it look however you want. 

The running example uses the Products and Categories tables found in the Northwind database.  The Products table has a foreign key column that refers to the row in the Categories table that contains the category name and description for the corresponding Products.  The sample page contains a DetailsView that allows the user to edit a single row in the Products table.  The Category row in the DetailsView contains a TextBox.  When the user clicks in the TextBox the popup is displayed showing the user what the valid categories are.  Here are the steps I took to build this sample ...

Create the Products and Categories DataSources

My first step was to define the 2 DataSources for this example.  One for fetching the row from the Products table that we will be editing, and another for fetching all of the valid categories from the Categories table.  For this example I am using the SqlDataSource for both of these items.  For simplicity I have hard-coded the Products query to only return productid '1'.   Here is the markup for these DataSources

<asp:SqlDataSource ID="sqldsProduct" runat="server" SelectCommandType="Text"
    SelectCommand="
        select 
            p.productname, 
            p.unitprice, 
            p.quantityperunit, 
            p.unitsinstock, 
            p.unitsonorder, 
            c.categoryname, 
            c.categoryid 
        from 
            dbo.products p 
            inner join dbo.categories c on 
                p.categoryid = c.categoryid 
        where productid = 1" 
    ConnectionString="todo" />
<asp:SqlDataSource ID="sqldsCategories" runat="server" SelectCommandType="Text"
    SelectCommand="
        select 
            c.categoryid, 
            c.categoryname 
        from 
            dbo.categories c"
     ConnectionString="todo" />  

Create the DetailsView for Displaying the Product

Next, I created the DetailsView that displays the Product.  I set the DataSourceID to 'sqldsProduct' and adjusted a few of the presentation specific items including the HeaderStyle and FieldHeaderStyle.  After that, I add all of the columns except 'category' to the Fields collection as standard BoundFields.  Next, I added the 'category' field as a TemplateField as follows:   

<asp:TemplateField HeaderText="Category">
    <ItemTemplate>
        <asp:TextBox ID="txtCategory" runat="server" Text='<%# Eval("categoryname") %>' />
        <asp:Panel ID="pnlCategories" runat="server" CssClass="popupControl">
            <div style="border: 1px outset white; width: 275px">
                <asp:UpdatePanel runat="server" UpdateMode="Conditional">
                    <ContentTemplate>
                        <asp:RadioButtonList 
                            ID="rdoButtons" runat="server" 
                            DataSourceID="sqldsCategories" DataTextField="categoryname" 
                            DataValueField="categoryid" AutoPostBack="true" 
                            SelectedValue='<%# Bind("categoryid") %>' 
                            OnSelectedIndexChanged="RdoButtons_SelectedIndexChanged" />
                    </ContentTemplate>
                </asp:UpdatePanel>                                
             </div>
        </asp:Panel>
        <ajaxToolkit:PopupControlExtender 
            ID="popupControl" runat="server" TargetControlID="txtCategory" 
            PopupControlID="pnlCategories" CommitProperty="value" Position="Top" />
    </ItemTemplate>
</asp:TemplateField>

The important items here are the following:

  1. I bound a TextBox (txtCategories) to the 'categoryname' field from the DataSource.  This way the name of the category is displayed in the TextBox when the page is initially rendered and pushed back to the DataSource when UpdateItem is called on the DetailsView
  2. I added a Panel that contains the control I want displayed as a popup.  Inside the Panel I define a RadioButtonList that is bound to the 'sqldsCategories' DataSource.  I bound the SelectedValue property to the 'categoryid' column from 'sqlProducts' DataSource 
  3. I added the PopupControlExtender, pointing to the Panel and the TextBox.  Now when the user clicks in the TextBox, the panel is displayed.  I set the CommitProperty to 'value' so when I call Commit on the PopupControlExtender, it sets this property with the value I provide. 
  4. The RadioButtonList is contained in an UpdatePanel and AutoPostback='True' so everytime the user selects an option, a partial postback occurs and the code in the RdoButtons_SelectedIndexChanged event handler is run.  This handler passes the text from the selected radio button to the PopupControl's Commit function which in turn moves it back to the txtCategories TextBox back on the client.
protected void RdoButtons_SelectedIndexChanged(object sender, EventArgs args)
{
    RadioButtonList rdoButtons = (RadioButtonList)sender;
    PopupControlExtender popupControl = 
        (PopupControlExtender)rdoButtons.NamingContainer.FindControl("popupControl");

    // Popup result is the selected category
    popupControl.Commit(rdoButtons.SelectedItem.Text);
}

Improvements

That's it for the sample, but there are a few areas that can be improved further.  The first is that there should be a way to Commit the value from the selected radio button without executing a partial postback.  The PopupControl exposes a CommitScript property that I think can be used to keep everything on the client.  Also,  it would be nice to add a 'Cancel' or 'Close' button to the popup that dismisses it without changing the selected item.  Finally, I think it would also be interesting to combine this with some of the other AjaxControlToolkit controls like DropShadow or RoundedCorners to improve the visualization even further.  I will explore these items in a follow-up post.

Enjoy!


TrackBack

TrackBack URL for this entry:
http://mattberseth.com/blog-mt/mt-tb.fcgi/54

Comments


Posted by: Kevin on September 7, 2007 07:39 PM

Great Example..Thnx

I was trying to use few drop downs controls in the popup Extender with an Ok button. I am not able to get Click Event....Any Idea.


I need postback on a Button Click insted of RadioIndex changed.

Posted by: Joe Montana on February 5, 2008 05:59 AM

Hi guys,
i suprisingly have solved a similar issue, just adding name_control.enabled = true, after adding the list items. Note that using datasource and databind, did'nt either worked.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Sponsor

Recent Comments

  • Joe Montana wrote: Hi guys, i suprisingly have solved a similar issue, just adding name_control.enabled = true, after ...
  • Kevin wrote: Great Example..Thnx I was trying to use few drop downs controls in the popup Extender with an Ok bu...

Sponsor