Google+ Peter Bromberg's .NET Blog | All Things Programming

Peter Bromberg's .NET Blog All Things Programming

Using the AJAX Autocomplete Extender With Multiple Values

18. May 2013 12:50 by admin in ASP.NET

The MS Ajax Autocomplete extender allows you to change a texbox into a typeahead dropdown list allowing you to select one of the matches to a search. Here is how it can be used to handle  both display text and value items with a bit of Javascript.


First let’s have a look at key elements of the markup:

<script type = "text/javascript">function clientItemSelected(sender, e) {
             $get("<%=hfZipcode.ClientID %>").value = e.get_value();
    </script><asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true"></asp:ScriptManager>
        <asp:Label runat="server" ID="lblText" Text="Enter City Search string" />
        <asp:TextBox ID="txtZip" runat="server"></asp:TextBox>
        <asp:AutoCompleteExtender ID="AutoCompleteEx" runat="server"  TargetControlId="txtZip"
            DelimiterCharacters=";, :"
            OnClientItemSelected = "clientItemSelected" >
                            <%-- Make the completion list transparent and then show it --%>
                            <OpacityAction Opacity="0" />
                            <HideAction Visible="true" /> 
                            <%--Cache the original size of the completion list the first time
                                the animation is played and then set it to zero --%>
                            <ScriptAction Script="
                                // Cache the size and setup the initial size
                                var behavior = $find('AutoCompleteEx');
                                if (!behavior._height) {
                                    var target = behavior.get_completionList();
                                    behavior._height = target.offsetHeight - 2;
                           = '0px';
                                }" />
                            <%-- Expand from 0px to the appropriate size while fading in --%>
                            <Parallel Duration=".4">
                                <FadeIn />
                                <Length PropertyKey="height" StartValue="0" EndValueScript="$find('AutoCompleteEx')._height" />
                        <%-- Collapse down to 0px and fade out --%>
                        <Parallel Duration=".4">
                            <FadeOut />
                            <Length PropertyKey="height" StartValueScript="$find('AutoCompleteEx')._height" EndValue="0" />
          <asp:HiddenField ID="hfZipcode" runat="server" />
        <asp:Button ID="btnSubmit" runat="server" Text="Submit" 
            onclick="btnSubmit_Click" /> <asp:Label ID="lblMessage" runat ="server" />


Here is the associated codebehind class for the page, which includes the Page Method that returns the requested data:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Configuration;
using System.Data;namespace Autocomplete
{public partial class Default : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e){}[System.Web.Script.Services.ScriptMethod()][System.Web.Services.WebMethod]public static List<string> GetCompletionList(string prefixText, int count){using (SqlConnection conn = new SqlConnection()){conn.ConnectionString = 
                using (SqlCommand cmd = new SqlCommand())
                {cmd.CommandType = CommandType.StoredProcedure;cmd.CommandText = "GetZipInfoByCityName";cmd.Parameters.AddWithValue("@SearchTerm", prefixText);cmd.Parameters.AddWithValue("@maxRecs", 20);cmd.Connection = conn;conn.Open();List<string> zips = new List<string>();using (SqlDataReader sdr = cmd.ExecuteReader()){while (sdr.Read()){string item = 
                                   sdr["Zipcode"].ToString());zips.Add(item);}}conn.Close();return zips;}}}protected void btnSubmit_Click(object sender, EventArgs e){lblMessage.Text = "You selected " + hfZipcode.Value;}}

The trick for handling the value that gets submitted upon a selection is the little javascript clientItemSelected function. This is triggered by the OnClientItemSelected = "clientItemSelected" attribute of the Autocomplete extender. The downloadable code includes the SQL Server database files for a ZIP CODE database. Simply attach this database to your local copy of Sql Server and you should be ready to test it out. (3.33 mb)

An Easy Way to Render HTML From an ASP.NET UserControl

20. March 2013 09:59 by admin in

Often we need to call RenderControl on a UserControl to get the rendered HTML and be able to pass it to a PDF or Report generator. This can be problematic because you will get exceptions saying that the control must be within a FORM tag with runat=server. Also, If there are any AJAX script - related controls such as TextBoxExtenders, you will be warned that a ScriptManager is required. Here is an easy way to avoid these issues and get back "clean" HTML:

public static string RenderUserControl(Control ctrl)


Control control = null;

const string STR_BeginRenderControlBlock = "";

const string STR_EndRenderControlBlock = "";

StringWriter tw = new StringWriter();

Page page = new Page();

page.EnableViewState = false;

HtmlForm form = new HtmlForm();

form.ID = "__temporanyForm";


form.Controls.Add(new LiteralControl(STR_BeginRenderControlBlock));

// add a ScriptManager to prevent Ajax Extender control exceptions

ScriptManager m = new ScriptManager();



form.Controls.Add(new LiteralControl(STR_EndRenderControlBlock));

HttpContext.Current.Server.Execute(page, tw, true);

string Html = tw.ToString();

int start = Html.IndexOf("");

int end = Html.Length - start;

Html = Html.Substring(start, end);

// return the rendered HTTML and send it into the PDF generator

return Html;


ASP.NET Strongly Typed Data Controls

10. March 2013 11:49 by admin in

ASP.NET Web Forms introduced the concept of "templates",  which allow you to customize the markup emitted from server controls, and are typically used with data-binding expressions.

When using data-binding within a template today, you use late-bound expressions to bind to the data.  Below we are using the Eval() helper method to data-bind the "FirstName" and "LastName" properties from a list of objects data-bound to a repeater control:


    <asp:Repeater runat="server" ID="customers">



                First Name: <%# Eval("FirstName") %><br />

                Last Name: <%# Eval("LastName") %><br />





When performing 2-way data-binding today, you use the Bind() helper method like so:

<asp:FormView ID="editCustomer" runat="server" >



            First Name:

            <asp:TextBox ID="firstName" runat="server" Text='<%# Bind("FirstName") %>' />



            Last Name:

            <asp:TextBox ID="lastName" runat="server" Text='<%# Bind("LastName") %>' />


        <asp:Button runat="server" CommandName="Update" />



One downside with the above approaches is that the calls to Eval() and Bind() are late-bound - meaning you pass strings to represent the property names.  This means you don't get Intellisense for the member names, support for code navigation (like Go To Definition), nor compile-time checking support.

Strongly Typed Data Controls

The next release of ASP.NET provides the ability to enable strongly-typed data templates.  Specifically, we've added the ability to declare what type of data a control is going to be bound to, by way of a new "ModelType" property on data controls.  Setting this property will cause two new typed variables to be generated in the scope of the data-bound template expressions: Item and BindItem.

Developers can use these variables in data-binding expressions and get full Intellisense and compile-time checking support.  For example, below we've set the ModelType on an <asp:repeater> control to be a "Customer" object.  Once we do this we can switch from using Eval("FirstName") to instead use Item.FirstName to reference the property.

We get full Visual Studio code intellisense when we do so:


For 2-way data-binding expressions, we can also now use the BindItem variable and get the same strongly-typed benefits:

<asp:FormView ID="editCustomer" runat="server">



            First Name:

            <asp:TextBox ID="firstName" Text='<%# BindItem.FirstName %>' runat="server" />



            Last Name:

            <asp:TextBox ID="lastName" Text='<%# BindItem.LastName %>' runat="server" />


        <asp:Button runat="server" CommandName="Update" />



If we make a mistake while typing, we'll get instant feedback from the IntelliSense engine that something is wrong: