Five ASP.NET Controls You Might Be Craving

SP.NET is a terrific platform for Web applications. That does not mean that tricky coding is always one or two clicks away within a dockable and resizable Visual Studio .NET dialog box. Tricky solutions require tricky coding, just the kind of features that a wizard-driven environment and a general-purpose framework can’t provide. In this article, we’ll tackle five ASP.NET features that require wicked and creative code.

Have you ever heard about the “real programmer?” The real programmer is someone who makes a living putting one keyword after the next, abiding by some sort of syntax and semantics. Being strongly results-oriented, the real programmer gained a reputation for hating all the bells and whistles that inevitably surround any software technology. Wizards, black box components, and data binding? No, thank you. The real programmer makes a point of writing hundreds of lines of code to get full control over each execution step.

Frankly, I’ve found myself in the position of the real programmer more than once, especially regarding data binding. As a real programmer, I never used old Visual Basic data-bound controls. If you ever experienced the data-bound controls of early versions of Visual Basic, you know why. But the advent of the .NET Framework changed things quite a bit. The .NET Framework comes with a powerful data binding mechanism implemented for both Windows Forms and Web Forms.

Unfortunately but reasonably, the set of ASP.NET data-bound controls just don’t cover all possible scenarios; you can have automatic binding between a data source and a list of check boxes or radio buttons. But if you’re looking for a data-bound bulleted or numbered list of strings, prepare to face disappointment.

I’m not sure how you feel about that, but I craved a BulletList control for a while. Then, I made the decision to build it myself. Quite surprisingly, it wasn’t too difficult. It is probably a task within the reach of any programmer and not just “real programmers.”

1. Building a Bulleted List Control
The BulletList control can be built starting from the WebControl class. This class provides a default implementation for several handy UI properties, such as Font and ForeColor. By inheriting from WebControl, you don’t have to worry about common UI-related properties and can focus on the more specific attributes of the control.

The BulletList control needs at least four properties, as listed in Table 1.

Table 1: These are the properties of the BulletList control.

Property

Description

BulletListType

Indicates the type of bulleted list. Feasible values are defined in the BulletList enumeration: UL or OL.

DataSource

Gets and sets the data source associated with the control

DataTextField

Gets and sets the name of the data source field to be used to fill the list

Items

The collection of strings that represents the items added to the list

The Items property has a double role. For one thing, it is the internal buffer in which the data-bound information is parked before it is rendered to HTML. Because the property is marked as public, you can also use it to manually add strings of text to the list. This code snippet shows how to add extra items at the bottom of the list created after the data source.

   list.Items.Add("Plus this one!");

The DataSource and the DataTextField properties let you extract a particular column of data out of an ADO.NET container. The use of these properties is in no way different from analogous properties defined in other list-bound classes (e.g., CheckBoxList). The typical use you can make of them is shown in this next snippet.

   // Run the query   SqlDataAdapter adapter;   string cmd = "SELECT * FROM employees";   string conn = "SERVER=...;DATABASE=...;UID=...;";   adapter = new SqlDataAdapter(cmd, conn);    // Bind the control   DataTable table = new DataTable();    adapter.Fill(table);   bList.DataSource = table;    bList.DataBind();

The control also needs to override the DataBind method inherited from the Control class. When the DataBind method is called, the control loads the bound data source into the Items string collection. During the Render method (another overridden method), the control builds the bullet list, mixing together HTML tags and text strings. In HTML, you can have two types of lists: the classic bulleted list or a numbered list. In the former case, you create it using the

    tag; for the latter case, use the

      tag. Nested within those elements, there is one

    1. tag per each item to display.

      The control’s programming interface allows you to choose the type of bulleted list through the following enum type:

         public enum BulletType   {      UL,      OL   }

      A value of type BulletType is assigned to the BulletListType property. An enum type cannot be a collection of strings; only basic types can be used, such as int or double. By giving the entries in the enumeration the same mnemonic names of HTML tags, you can easily associate each of them with the correct string using the ToString method. Listing 1 shows how to render the BulletList control to HTML, based on the value of the BulletListType property.

      The full source code of the BulletList control is shown in Listing 2. Notice the technique used to generate the HTML for the control. The Render method?the procedure that calls into the CreatePanel method shown above?gets an HTML TextWriter object from the .NET Framework and sends text to it. You can implement the Render method in such a way that the code simply outputs text to the stream; alternatively, you can use a temporary instance of a control, configure it through properties, and then render it. The gain is that you end up with code far easier to read and maintain. This technique is frequently used within ASP.NET itself.

      To add IntelliSense support to the HTML view of the visual designer, you need to provide the schema of the control: an XSD file.

      Regarding Listing 1, the technique based on temporary controls might seem overkill. The following code would have worked great as well. Judge for yourself.

         output.WriteBeginTag("ul");   output.Write(HtmlTextWriter.TagRightChar);   foreach(string elem in Items)   {      output.WriteBeginTag("li");      output.Write(HtmlTextWriter.TagRightChar);      output.Write(elem);      output.WriteEndTag("li");   }   output.WriteEndTag("ul");

      Figure 1 shows the BulletList control in action based on this next bit of code.

         <%@ Register TagPrefix="expo"    Namespace="CodeMag.Controls"    Assembly="BulletList" %>   

      2. Make Your Control’s Schema Visible to VS .NET

      3. Truncate Text in Grid Columns
      A common problem for ASP.NET developers and UI designers is that often the text you want to display in a grid exceeds the maximum width of the column. In this case, having the text wrap to the next line within the same cell is a viable option, but not necessarily an elegant option. What if you want to emulate the behavior of the Windows listviews and show an ellipsis at the end of truncated strings?

      4: Two Rows for the Item
      When most programmers need to write reports of data, the DataGrid is the first control they look at. The DataGrid control meets most, but not all, common user requirements in these situations. One of the (very few) things the DataGrid can’t easily do is display data items on two rows. Let’s consider a typical scenario: a report with product information in which each item is represented by multiple table rows. For example, the first row could contain product ID and name, and the second row contains the product description. The DataGrid is not ideal for this task because its user interface is designed to associate one data item with one row. Using the Repeater control might make the task straightforward but at the price of losing many useful (and automatic) formatting and editing capabilities of the grid. Is there a viable way in the middle?

      With a Repeater, you could create multi-row reports by defining a table in the header template and then a couple of rows for each item. If you don’t mind using a Repeater, this is just fine.

               ......   
      ...
      ...

      The DataList control offers the same capabilities of the Repeater plus advanced styling and formatting properties that you wouldn’t readily sacrifice. Can you just use the DataList in lieu of the Repeater? As the code snippet above shows, when using the Repeater, you build the final table by combining HTML elements across templates. By design, you can’t take the same liberty with a DataList. Put another way, with a DataList you can’t place the opening tag of a table in the header and then close it in the footer. However, this doesn’t mean that you can’t have a multi-row item in a DataList.

      Figure 4: This is a table with multiple rows per item created using a DataList control.

      The secret for building HTML tables using a DataList is in the ExtractTemplateRows property of the control. It gets or sets a Boolean value that instructs the DataList to extract the constituent rows from any HTML table in the templates. The idea is that you define brand new tables in each template: header, item, footer. Next, if the property is set to true, the control extracts the rows from all child tables and combines them together to create a single, all-encompassing table. ExtractTemplateRows is set to false by default.

      The use of the property is subject to a few restrictions. The tables must all be defined using a well-formed tag. An exception is thrown if you define the table using the

      element with or without the RUNAT attribute. The tag corresponds to a Table control, which is the only one to expose rows and cells programmatically. This is valuable information that allows the DataList to build a new table joining the rows defined in all constituent tables. All non-row tags are ignored. Listing 3 shows the source code of a DataList control that exploits templated rows. In Figure 4, you can see a sample page in action.

      The ExtractTemplateRows property is helpful when you’re going to create quite a complex structure in which tables with different templates are to be merged together. You can use the ColumnSpan and RowSpan properties of the TableCell object to control the number of columns and rows the cell spans. When the ExtractTemplateRows property is set to true, the RepeatColumns, RepeatDirection, and RepeatLayout properties are ignored and do not affect the appearance of the DataList control.

      5. Manage Global Data
      In ASP and ASP.NET, the Application object represents the global state of the application. It contains data that is visible to all currently running sessions. In ASP.NET, though, the Application-intrinsic object is only one aspect of the Web application: the global state. To learn the best way to manage global data in Web applications, you should first fully understand the underpinnings of the ASP.NET runtime.

      The root class of an ASP.NET application is defined in the global.asax file. Any user code there defines a new class that inherits from HttpApplication. If global.asax is not specified, the base class HttpApplication is used as the application class. ASP.NET runtime creates as many instances of the application class as is needed to process simultaneous requests. For most applications, this number falls in the 1-100 range depending on the hardware, the server workload, and the configuration. Instances of the application class are pooled and reused to serve many requests. It is important to notice that application instances are used in a thread-safe manner, one request at a time. This fact has a few important implications.

      For one thing, users don’t need to worry about locking to access non-static members of the application class. In addition, application code can store per-request data in non-static members of the application class. However, if you store data in members after the EndRequest event has fired, it keeps the request alive?potentially for a long time. You should just avoid that.

      Just like any other class, the application class can have static members, but they are not thread safe. This means that the user code needs to provide appropriate locking around access to such members.

      In light of this, there are three ways to store the global state of an ASP.NET application:

      • Create a custom HttpApplication
      • class and define custom, non-static members
      • Define static members in the global.asax file
      • Stick to the ASP-style Application dictionary

      When you build an application using Visual Studio .NET, the project automatically creates a global.asax.cs file. It contains the application class derived from HttpApplication, typically named Global. To implement the first option, you can either change the base class to your custom class or add public non-static members to the Global class. Those members are automatically accessed in a thread-safe manner and are strong-typed data.

      If you don’t use Visual Studio .NET, static members are probably easier to define. A static member, in fact, can be defined directly in the global.asax file, as shown below.

         

      The Counter member is visible to all sessions as if it were stored in the Application object. To access the property from a page, use the following syntax.

         int n = ASP.global_asax.Counter ++;

      If you don’t particularly like the ASP.global_asax prefix, you can name the HttpApplication class using the ClassName attribute within the @Application directive.

         <%@ Application       ClassName="Globals"   Codebehind="Global.asax.cs"    Inherits="WebApplication1.Global" %>

      The preceding statement creates an alias for the ASP.global_asax class (or whatever name your global.asax class has). The alias, Globals in this sample code, can be used throughout your code wherever ASP.global_asax is accepted.

         Response.Write(Globals.Counter.ToString());

      Consider that concurrent access to the Counter property is not serialized and you are responsible for inserting any needed lock.

      A final word needs to be stated about a couple of very special events, Application_OnStart and Application_OnEnd. From the perspective of ASP.NET, they aren’t even application events but just callbacks made to the user code for classic ASP compatibility. Both events are fired only once per application lifetime, but not for every application instance. This means that changing non-static members in these methods affects only one application instance, not all instances. For this reason, the per-application-instance initialization could be done either in the constructor of the class or by overriding the Init method of the HttpApplication class.

      I started this column blinking at the virtual category of real programmers. In spite of the jokes, real programmers need to be productive but technically straight-to-the-point and knowing the theory behind it all. In this article, I tried to merge a few ASP.NET issues that gave me quite a hard time. I hope that your experience is easier now. Enjoy it!

      Share the Post:
      Share on facebook
      Share on twitter
      Share on linkedin

      Overview

      The Latest

      microsoft careers

      Top Careers at Microsoft

      Microsoft has gained its position as one of the top companies in the world, and Microsoft careers are flourishing. This multinational company is efficiently developing popular software and computers with other consumer electronics. It is a dream come true for so many people to acquire a high paid, high-prestige job

      your company's audio

      4 Areas of Your Company Where Your Audio Really Matters

      Your company probably relies on audio more than you realize. Whether you’re creating a spoken text message to a colleague or giving a speech, you want your audio to shine. Otherwise, you could cause avoidable friction points and potentially hurt your brand reputation. For example, let’s say you create a

      chrome os developer mode

      How to Turn on Chrome OS Developer Mode

      Google’s Chrome OS is a popular operating system that is widely used on Chromebooks and other devices. While it is designed to be simple and user-friendly, there are times when users may want to access additional features and functionality. One way to do this is by turning on Chrome OS

      ©2023 Copyright DevX - All Rights Reserved. Registration or use of this site constitutes acceptance of our Terms of Service and Privacy Policy.

      Sitemap