Wednesday, August 15, 2007

First Experiences With VS2K8 Part 3

This is the third in a series of posts I'm going to be making about my experiences with Visual Studio 2008 and .NET3.5. You might also be interested in the first and second posts. At the end of the last post I had successfully created my basic data model and used it on a web page to display a list all of my customers. The problem was that the list really displayed ALL of my customers and the page was way too long. Nobody would want to sit there and sift through all of the rows much less wait for them to download so I figured the next step would be to add sorting and paging. Luckily for me this couldn't be easier. I simply set the AllowPaging and AllowSorting properties of the GridView to true and everything else was taken care of. I also used the AutoFormat functionality on the GridView to select a simple display style. I chose Classic. I now had a GridView that was displaying all of my Customer data in a fairly accessible way and it didn't look half bad. Since our phone operators would be taking calls from customers placing orders the first step in the system should probably be to find a customer and now I had a way to do that. But it still wasn't ideal. A user would have to page through customers to find the customer they wanted. Of course a search box would solve the problem. And I decided a little associated AJAX magic would make for a really nice UI. The search box would work sort of like an autocomplete box but instead of a drop down appearing with likely candidates when the user started typing I decided to populate the whole GridView with the likely candidates. I also decided not to start the autocomplete operation until after at least 3 characters had been typed. First of all let me admit that I couldn't figure out how to programmatically configure the LinqDataSource's where clause the way I needed to so I decided to ditch it. I deleted that control and the GridView's reference to it. Then I was ready to proceed with getting the autocomplete working. To accomplish this I first added an HTML TextBox Input element to the page. I didn't use the ASP:TextBox control becuase it's easier to set the 'onKeyUp' event on the HTML version. I did however set the input element's 'runat=server' property so that it would be easy to access the value of the box in my code behind. For the 'onKeyUp' property I set it to call a javascript function called 'onKeyUp()'. I'll get to that function in a bit. Next I wrapped my existing GridView with an UpdatePanel and its associated ContentTemplate. I set the onload property of the UpdatePanel to call the server side method "updatePanel1_Load". This is to facilitate the auto-complete functionality. Here's an explanation of how that works: The search textbox has a function called 'onKeyUp()' assigned to its 'onkeyup' event. This function is defined as: function onKeyUp() { var tb = $get('<%= searchTB.ClientID %>', null); if (tb.value.length > 2) { __doPostBack('<%= updatePanel1.ClientID %>', ''); } } This javascript function executes on the client. It gets a reference to the search textbox. It checks the length of the value there and if it's longer than two characters it triggers an AJAX postback that appears to come from the UpdatePanel. Notice that the ids of the search textbox and the UpdatePanel are being generated at runtime by the ASP engine. This is because ASP.NET prepends the IDs of containing controls onto the ID of their children controls. (So if the textbox's ID is 'searchTB' but it's in an UpdatePanel called updatePanel1 its rendered ID at runtime will be updatePanel1_searchTB, not just searchTB. Every control though has a ClientID property which returns the rendered value of the ID rather than that assigned to it programmatically.) The postback operation triggered by the above call will then cause the UpdatePanel's OnLoad event to fire and since we assigned the server side method 'updatePanel1_Load' to the onload property this method will now fire. It's contents are: protected void updatePanel1_Load(object sender, EventArgs e) { string searchTerm = searchTB.Value; if (searchTerm.Length < 2) { return; } OrdersDataContext db = new OrdersDataContext(); var query = from cust in db.Customers where cust.lastName.StartsWith(searchTerm) select cust; gv1.DataKeyNames = new string[] { "CustID" }; gv1.DataSource = query; gv1.DataBind(); } Put this all together and when the page loads it first presents the user with just a textbox. Once the user types three characters the client side script fires an AJAX postback and when that returns a GridView appears with all of the customers whose last names start with the letters in the text box. Each additional letter the user types further refines the results. In my next post we'll make this page a little more user friendly and then we'll look into giving the user a way to actually select the proper customer when they see the record on the screen.

No comments: