Modular JavaScript enabled user controls in ASP.NET 2.0
Posted by jimblackler on Dec 23, 2007
ASP.NET is great at separating design and code elements on the server side. This extends to a powerful yet simple way of adding your own custom controls to your ASP.NET websites.
It provides a great method to connect HTML elements in an .ascx and back end server code in a .cs file. This approach is quick to get going and has long term scalability too. However, on the web today, developers will want to have the option of client side dynamic code too, in the form of JavaScript elements to add to the control.
Microsoft’s suggestions are useful but only suitable for simple applications such as mouseover effects. This is because they tell you how to add isolated fragments of JavaScript to DOM elements. I wanted a single JavaScript class that had permanent links to DOM elements.
Lately they also provide Ajax tools for ASP.NET, and a framework of Ajax controls. There are some nice controls with these tools. However even with everything installed, what you don’t get is an way of adding your own JavaScript enabled custom controls which is as easy as adding a Web User Control from the Add New Item wizard. I was expecting to see a pattern that simply provided a client side .js file to complement the server side .cs and .ascx files. The AJAX tools seem rather over-complex compared to vanilla ASP.NET 2.0, and worse still, this approach requires .dlls to be installed on the server side. I had to telephone my host to ask them to add the components.
I’ll explain the simpler system I have developed. My aims were:
- To neatly include all the JavaScript in a .js file, containing a parallel JavaScript class for the control.
- To give the JavaScript part access to DOM elements set up in the .ascx (server side) part of the control (either runat=”client” elements type or elements created with runat=”server” controls).
- To give the JavaScript part access to the attributes set on the server side of the control.
- To allow unique HTML IDs, so that there can be more than one control of that type per page, with each control operating independently.
My method enables links not only between server and client sides of a user control, but between controls and their parent elements on the client side (just as could be done on the server side). Think of it as “client-side code behind”.
How it works
- An ASP.NET control is set up in the usual way with code behind which adds the .ascx and .ascx.cs files to the project.
- The developer adds a .ascx.js file to the project for the client-side components, with a matching name.
- function TrackBar(clientID, minimum, maximum, smallChange, barPixelWidth)
- {
- //....
- }
- The developer adds two pieces of JavaScript to the .ascx. Firstly, a client-side include to the .ascx.js script:
- <script type="text/javascript" src="TrackBar.ascx.js"></script>
Below that, a script to create a new instance of the JavaScript object with the expected parameters detailed in the previous step.
- <script type="text/javascript">
- <%=ID%>= new TrackBar('<%=ClientID%>', <%=Minimum%>, <%=Maximum%>, <%=SmallChange%>, <%=BarPixelWidth%>);
- </script>
The “<%=ID%> =” before the ‘new’ creates JavaScript code that sets a variable that contains the JavaScript object associated with the control that is named the same as the server side ID for the control. This could allow JavaScript in the parent page to interact with the control object of the child control.
This contains a single class wrapped with a single function of the same name, and taking as parameters the client ID of the the control, and any properties that the JavaScript object requires to receive from the server-side part. e.g:
The ClientID allows the JavaScript to have access to the DOM relating to its specific instance using the getElementById() function. This is because is possible to predict client IDs of child DOM elements by using the control’s own parent ID. For instance a div declared with <div runat=”server” id=”content”> in a control with client ID “myControl1” will have the client ID “myControl1_content”. In code this could be obtained with getElementByID(clientID + “_content”);
The use of runat=”server” is necessary because although a static client ID could be provided, this would not have a name unique to the page, and would therefore not allow more than one control of that type per form or parent control.
Example
An example with an online demo and full source is presented here. I’ve developed a TrackBar control for ASP.NET similar to the control in Windows Forms. This control is for number entry by a user viewing a web page. It presents a number as a text box, but if the user has JavaScript enabled it also shows a visual slider that can be manipulated with the mouse. The effect on the value can be seen in real time.
The control changes the text in the TextBox which gives a return path of data to the server side. An example of this can be seen in the code in the Default.aspx.cs file.
In addition, a callback can be added to an instance of a TrackBar control on the client (JavaScript) side. An example of this can be seen in the code in Default.ascx.js, where the position and content of a text fragment is changed in real time as the slider is altered.
Breathing exercise timer for Windows, with .NET 3.5, WPF and Visual Studio C# Express 2008
Posted by jimblackler on Dec 2, 2007
A family member requested I write them a simple windows program to help them with some medically-prescribed breathing exercises. For the exercise (which is designed to lower blood pressure) you have to breath in for six seconds, and out again for six seconds. In the absence of a commercial timer available to do this, a dedicated timer program on PC is the next best thing. The program simply displays a bar-chart type graphic with the bars appearing and disappearing to indicate the six second intervals.
A tiny project like this was the perfect opportunity to take the newly-released VS C# Express 2008 for a spin. Initial impressions are good, just like Express 2005 almost everything is there for professional development. It offers both Windows Forms and WPF as options on the New Project wizard, but it seems only to offer 3.5. In other words there seems no easy way of targeting 2.0 or other .NET versions from the wizard. I can confirm that 2.0 projects do load though (after running the conversion wizard) so it must be possible.
I like the WPF designer and the massive flexibility that WPF gives the developer in UI development. For this application, it was possible to add geometric shapes to the interface, which would have been hard in the Windows Forms designer. Also it meant that the window can be set to scale when resized. Being able to switch between a massive timer display and a tiny one could be very useful for users of a program like that.
For reference, the way to have WPF content automatically scale is to wrap the content in a
Installer for One to Six program