Chapter 3. Controlling Your Development Experience

In This Chapter

  • Showing stuff to the user

  • Getting some input from the user

  • Binding

  • Styling with the best

  • Making sure the site is accessible

  • Constructing user controls

  • Adding custom controls

ASP.NET is a rendering engine. It takes preset batches of functionality and renders it into HTML. For instance, ASP.NET can take a database table and a little bit of layout information and make a nice, dynamic HTML table.

Rendering engines are a good idea in the W world. With a bunch of different implementations and versions, your rendering engine can produce different user markup out of the same effective code base.

ASP.NET does this well. You can tell it to make mobile-device markup and text-only markup and rich Internet Explorer markup from the same ASP.NET file, and it will do an okay job.

This is possible because of Web controls. Web controls are controls that ASP.NET renders into client-side markup, like HTML, CSS, and JavaScript. Well-programmed controls protect the developer from the implementation details but can still do what is needed to be done when the time comes.

Web controls aren't anything special. Basically, they show a pretty text box in the designer pane of Visual Studio, and then emit text — an <input> tag — when called upon to do so.

ASP.NET has a lot of included controls, many other controls are available from third-party providers, and you can even build your own and base them on existing controls. It's a good system.

Showing Stuff to the User

Web surfers want to look at stuff. For them to look at it, you have to show it. Most of the controls in the ASP.NET control library are about showing things to the user.

Although there are a lot of controls, only some of them apply to the subject matter of this book — C#. This doesn't mean you shouldn't use them, but they are more about the HTML and less about the code on the server. So I am just going to cover a few controls. For more, please pick up ASP.NET For Dummies.

Labels versus plain old text

The most basic item on an average Web page is text. Take a look at a normal site, like Microsoft.com. You find a text box, maybe two; a handful of images also. Most of what is there is text.

Text comes in a few flavors in ASP.NET. The two I want to talk about are Label text and, well, text text. Label text is text inside a named span that you can change with C# code. Then there is just normal text on the page. This text is static — downloaded to the client just as you typed it.

To see what I mean, start a new Web project. Just follow these steps:

  1. Click the New Project button and select C# ASP.NET project.

    I called mine Chapter 3.

  2. Make a new ASP.NET page called Text.aspx.

  3. Change to Design view.

    There will be a default div that you saw in Chapter 2. Put your cursor between the <div> and the </div> and then type something innovative, like This is new text. Then press Enter.

  4. On the new line, drag a Label from the Toolbox.

    Your finished product should look like Figure 3-1.

  5. Double-click elsewhere on the form to get to the code-behind.

  6. Change the value of the label in the Page.Load event handler by setting the Text property. The new handler should look like this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    namespace Chapter_3
    {
        public partial class Text : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                Label1.Text = "This is some text from the codebehind.";
            }
        }
    }
  7. Press <F5> to launch the application.

    You'll see that the label text was set by the C# code.

How to decide between labels and text? It's usually easy. Use a label if the text will need to change based on input from the user or the server. Use text if the text is static. A description of an item that is loaded from a database? That's a label. Your CEO's bio? That's text.

There is text, and there is text.

Figure 3-1. There is text, and there is text.

Images

Images are next to text in the realm of standard Web site fare. It's a complex topic because few programmers are graphic artists, and making nice images that fit together and look good is hard.

Nonetheless, sometimes you just want to show a picture on a page. Just as with text, there are two ways you can go about this. (Okay, there are more than two.) You can use the HTML <img> tag, or you can use the ASP.NET Image control.

Differences? Same as the text: If you need an image that you can manage from the C# side of things, use an image control: a product image, for example. If it is just a static image, like the picture of your CEO, then use the HTML tag.

Just follow these steps to add an image with ASP.NET's Image control:

  1. Add two images to your project by right-clicking the project and choosing Add

    Images

    You can find two images, or download some. I used a drum and a tuba. (It's college football!)

  2. Add a new page called Images.aspx.

  3. Drag one of the pictures right into the box that denotes the div.

    You'll get the Accessibility Properties dialog box, and then the picture will just show right up. Press Enter a few times to make some space.

  4. Drag an Image control from the Toolbox onto the page where the cursor is sitting.

    It should appear as a broken image. That's okay.

  5. Double-click elsewhere on the page to get the Page.Load event handler and switch to Code View.

  6. Just like we did in the Text example, set the visible property of the control. In this case, it is ImageUrl. The new code should look like this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    namespace Chapter_3
    {
        public partial class Images : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                Image1.ImageUrl = "tuba.gif";
            }
        }
    }
  7. Right-click the Images.aspx page in the Solution Explorer and select Set as Start Page from the context menu.

  8. Press <F5> to see it run.

You are probably getting the idea by this point. You can use HTML and set static values, or you can use the ASP.NET controls and set dynamic values. In the examples here, we are obviously just setting "static" dynamic values, but we could be reading from a Web service, a database, or even calculating the values. Images can be listed from a directory. Text could be generated and read into a table. The options are endless.

Panels and multiviews

Managing all these text blocks and images can be rough. ASP.NET provides a number of tools that help, including the two following tools.

  • Panels are just divs that you can manage in code-behind. Just like the text and images we added earlier, panels can be named and controlled in C#. The server will process changes before it sends the HTML to the browser. This helps to break the content into manageable groups.

  • Multiviews are essentially containers that hold a lot of panels. You can use them for wizards and tag groupings. They help to manage the panels, which help manage the content. For more information, search MSDN for ASP.NET Multiview.

From the client's perspective, panels and multiviews are effectively the same structure, but they provide developers with a few options. For instance, the multiview shows one view only of itself by default, whereas you have to hide panels that are not in use.

Tables

Tables work like other Web controls. In HTML, you have the basic <table>, <tr>, and <td> tags. In ASP.NET there is a Table control, with TableRows and TableCells. If you add an ASP.NET table, it looks like this:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Tables.aspx.cs"
    Inherits="Chapter_3.Tables" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.
    w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

        <asp:Table ID="Table1" runat="server">
            <asp:TableRow runat="server">
                <asp:TableCell runat="server"></asp:TableCell>
                <asp:TableCell runat="server"></asp:TableCell>
                <asp:TableCell runat="server"></asp:TableCell>
            </asp:TableRow>
            <asp:TableRow runat="server">
                <asp:TableCell runat="server"></asp:TableCell>
                <asp:TableCell runat="server"></asp:TableCell>
                <asp:TableCell runat="server"></asp:TableCell>
            </asp:TableRow>
<asp:TableRow runat="server">
                   <asp:TableCell runat="server"></asp:TableCell>
                   <asp:TableCell runat="server"></asp:TableCell>
                   <asp:TableCell runat="server"></asp:TableCell>
               </asp:TableRow>
           </asp:Table>

       </div>
       </form>
   </body>
   </html>

So what's the point of creating tables this way? Well, you can name those rows and cells, and then manage then in the code-behind using C#. In all honesty, though, that's not how I recommend doing things.

Tables are good for two things — layout and tabular data. Layout has been superseded by CSS. I recommend you use CSS to lay things out.

For tabular data, tables still work. However, there is a more interesting solution. The GridView (found in the Data section of the Toolbox) is just as functional — and it is bindable. We chat more about that in the Binding section later.

Getting Some Input from the User

Acquiring input from the user is one of the most significant processes that Web developers do. Data-active Web is all about interactivity; Web 2.0 is all about interactivity. Getting information from a user is job one.

You can do a lot of things to get input from the user, but there is a subset of the controls that is generally considered to be "User Input." You'll use those controls a lot.

Using text input controls

The most obvious form of collecting data from a user is the text input boxes, as shown in Figure 3-2. In HTML there are three defined controls: the textbox, the password, and the textarea. The TextBox ASP.NET control handles all of those. A TextMode property tells IIS how to render the control.

To use the TextBox control, drag it into the designer from the Toolbox. We can change the property of the control instance — the only other significant element — in the ASP.NET markup, the property panel, or the C# code.

The properties that we are the most interested in include:

  • ID: The name that you use to reference the control in the C# code. This needs to be set first, before you can use the control.

    The three text inputs, all in a row.

    Figure 3-2. The three text inputs, all in a row.

  • TextMode: This determines the type of text box that gets rendered, as I mentioned.

  • MaxLength: The maximum number of characters that the user can type in the field. Note that this doesn't work when the TextMode is defined as TextArea.

  • Height and Width: The size that the text box appears on the page.

  • CssClass: The style sheet class that the control will be rendered to use. Must be used in conjunction with a style sheet.

  • Enabled: Marks if the field can be typed in by the user.

In the example in Figure 3-1, I just dragged the TextBox control onto the designer three times and set each to the three different TextModes. Here is the resultant ASP.NET markup:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TextInput.aspx.cs"
    Inherits="Chapter_3.WebForm1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.
    w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
1 - The TextBox<br />
           <asp:TextBox ID="TextBox1" runat="server">The TextBox</asp:TextBox>
           <br />
           <br />
           2. The TextArea<br />
           <asp:TextBox ID="TextBox2" runat="server" TextMode="MultiLine">The
       TextArea</asp:TextBox>
           <br />
           <br />
           3. The Password<br />
           <asp:TextBox ID="TextBox3" runat="server" TextMode="Password">The
       Password</asp:TextBox>

       </div>
       </form>
   </body>
   </html>

In order to set properties in the C# code, I would refer to the ID, as set in the property panel. If you use the defaults (don't do this in real code, make real names for controls), configuring the first text box might look something like this:

public partial class WebForm1 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        TextBox1.MaxLength = 20;
        TextBox1.Height = 22;
        TextBox1.Width = 135;
        TextBox1.Enabled = true;
    }
}

Using single-item selection controls

After collecting text, the next most common user-input gathering operation is asking them to choose an item from a list. In HTML, you can do this with check boxes, radio buttons, or drop-down lists. (See Figure 3-3.)

The single selectors.

Figure 3-3. The single selectors.

ASP.NET provides for all of these items:

  • The Boolean check box: This is just one single check box where the answer is Yes or No. This is still considered a single item selection even though there is only one item to select from and is usually used to represent a Boolean or bit in the C# code. It is represented by the checkbox control.

  • The radio button list: Radio buttons are nice because they prevent the user from selecting more than one option while seeing all the options. Lists are an interesting beast, because they can be bound to collections. We cover that in the next section, "Binding." This control is radiobuttonlist.

  • The drop-down list: Represented by the dropdownlist control, this type of list allows the user to click to see the list, and then click one item, which then closes the list. It can also be bound to a collection.

Here is the code for all three. Note that both the dropdownlist and the radiobuttonlist use the listitem control to render the list items.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="SingleItem.aspx.cs"
    Inherits="Chapter_3.SingleItem" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.
    w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

        1. The Checkbox<br />
        <asp:CheckBox ID="CheckBox1" runat="server" />
        <br />
        <br />
        2. The Radio Button List<br />
        <asp:RadioButtonList ID="RadioButtonList1" runat="server">
            <asp:ListItem>Item 1</asp:ListItem>
            <asp:ListItem>Item 2</asp:ListItem>
            <asp:ListItem>Item 3</asp:ListItem>
            <asp:ListItem>Item 4</asp:ListItem>
        </asp:RadioButtonList>
        <br />
        3. The dropdownlist<br />
        <asp:DropDownList ID="DropDownList1" runat="server">
            <asp:ListItem>Item 1</asp:ListItem>
            <asp:ListItem>Item 2</asp:ListItem>
            <asp:ListItem>Item 3</asp:ListItem>
            <asp:ListItem>Item 4</asp:ListItem>
        </asp:DropDownList>

    </div>
    </form>
</body>
</html>

Using multiple-item selection controls

Sometimes you want the user to be able to choose more than one of the items available in a list. HTML has two controls that handle that: the listbox and the checkbox list. (See Figure 3-4.)

Controls for multiple selections.

Figure 3-4. Controls for multiple selections.

ASP.NET replicates these, like this:

  • The listbox: This list is a lot like a dropdownlist, except there is no expansion required — you see the expanded list right away, scroll bar and all. To select more than one item, the user is usually required to hold down the control or command key while clicking.

  • The checkboxlist: This is exactly what it sounds like: a list of check boxes. It looks just like a radio button list, except with check boxes. You can see what I mean in Figure 3-4.

Here is the code for these. As with the dropdownlist, the listitem is used to show the items. If it were databound, the listitems would not be there — they would just be rendered from the data source at runtime.

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

        1. Checkboxlist<br />
        <asp:CheckBoxList ID="CheckBoxList1" runat="server">
            <asp:ListItem>Item 1</asp:ListItem>
            <asp:ListItem>Item 2</asp:ListItem>
            <asp:ListItem>Item 3</asp:ListItem>
            <asp:ListItem>Item 4</asp:ListItem>
        </asp:CheckBoxList>
        <br />
2. Listbox<br />
        <asp:ListBox ID="ListBox1" runat="server">
            <asp:ListItem>Item 1</asp:ListItem>
            <asp:ListItem>Item 2</asp:ListItem>
            <asp:ListItem>Item 3</asp:ListItem>
            <asp:ListItem>Item 4</asp:ListItem>
        </asp:ListBox>

    </div>
    </form>
</body>
</html>

Using other kinds of input controls

ASP.NET provides a number of other input types that are combinations of the above, or are nontraditional inputs. (See Figure 3-5.) They are all special-use controls, but they need to be in your toolbox so you can use them when the need arises.

The stragglers.

Figure 3-5. The stragglers.

They include the following input types:

  • FileUpload: The FileUpload does exactly what it says. It creates an HTML input of type File and makes the form enctype (encoding type) into multipart form-data. This allows the Web server to accept a long stream of binary data, which you can then capture with a streamreader.

  • Imagemaps: Imagemaps are nearly relics of a bygone era. Essentially, they allow you to mark off pixel by pixel maps on top of images and then assign regions within those maps to URLs or other actions.

    This control assists you by giving you the framework. You still have to provide the map. Now, usually people use separate images.

  • Calendars: The calendar control is just a textbox that helps the user format dates properly. It works well. There are a ton of formatting options, too — check them out in the property panel.

There are others. I might have covered all the things you will see in the ToolBox, but there is a lot more out there. What you need to remember are the basics — they are visible controls with ASP.NET implementations and HTML output. You can use the property panel, the markup, or the C# code to change the properties. And you can bind them to objects in your code — which we discuss later in this chapter.

Submitting input with Submit buttons

After you get all this input into a form, you need the user to send it to you. The basic way to do this is through the Submit button.

In Chapter 1, I talk about the PostBack event, and how Microsoft used JavaScript to change the way the posting of forms back to the server works. The Submit button is how one does this.

Let's be clear — any control can cause a postback. If you set an event handler for an event in a control, it will cause a postback. You can save off the form data at any point once it gets back to the server. We use the Submit button because it is what the user is used to.

The ASP.NET default controls have three buttons.

  • Button is just what it says — an input of type submitted in HTML.

  • ImageButton is a button control that has a built-in src property for images.

  • LinkButton just shows an HTML anchor and treats it like a button.

We use one of these for nearly every page where we accept user input. Most of the time, the users expect it.

Data Binding

Getting the data into a control in a Web page isn't enough. There needs to be some way to persist (save for reuse) that information after the data is entered. Data binding is the answer.

Data binding tells a control what member of the underlying class to get its data from. For instance, if you have a collection of Apple objects with a property of Color that you want to show in a text box, you can bind the value Apple.Color to the Text property.

But things get more interesting than that. Let's say that you want to provide a list of colors and allow the user to select the color of the object in question. You can do that by binding the list of a collection and the selected value to the SelectedItem property of the list control. If you want to show the color itself, you can bind to the FontColor property of a text control.

Setting up your markup for binding

Back in the Active Server Page days, you put all your data on the page by simply printing it there. Sounds simple but it had a lot of problems. Foremost, your form had to have a lot of knowledge about the data it was showing. This is a bad thing. Anyway, the format for doing it was

<%= ThisIsWhatIWantToPrint %>

If you needed a list, you looped in the surrounding code. If you needed a method result, you just put the method right in there. What you saw was what you got.

Data binding is the more enlightened form of getting data on the screen. The controls that are built into ASP.NET know how to handle data on their own, so long as that data meets some basic specifics.

Data binding is accomplished by setting a property of a control to a member of the underlying class. For a single control, like a text box, you just set the property in question, like this:

<asp:Label ID="Label1" runat="server" Text='<%#
   IAmBindingToThisVariable %>' />

If you are binding to a repeating control, like a Grid or a ListBox, then you set the DataSource property. I show you how to do that in the next section, "Bindings in code."

Note

The variables you are binding to need to be in the code-behind, and be public. If they aren't, you will get runtime errors. That's also why binding in the code is a good idea, which we do in the next section.

Right now, let's talk binding in the markup. Here's all you need to do to set up your markup for binding:

  1. In the Chapter 3 Web project that we have been adding pages with controls to, right-click and choose Add New and then Class.

    I named my class Show.

  2. Click OK, and then put this simple data class in there. This class is just for example — it could be a database or a data class or an Entity Framework model.

    using System;
    
    namespace Chapter_3
    {
        public class Show
        {
            public int ID { get; set; }
            public String ShowTitle { get; set; }
            public String EpisodeTitle { get; set; }
            public DateTime ScheduledTime { get; set; }
            public int Channel { get; set; }
        }
    }
  3. Open the Text.aspx file in the Chapter 3 project.

  4. Double-click the design surface to get to the code-behind.

    If any code already appears in the Page.Load, you can delete it.

  5. Add code to the Page.Load to make a mock Show object.

    In a real project, you would get this object from the database or the service layer. For this example, I just use mock code:

    Show show = new Show { ID = 1, Channel = 5,
    EpisodeTitle = "ASP.NET Databinding", ScheduledTime
    = new DateTime(2009, 4, 12, 12, 0, 0), ShowTitle =
    "The C# Show" };
  6. We need to tell the page that we are going to be data binding. Add a Page.DataBind() call at the end of the Page_Load.

    The finished method looks like this:

    protected void Page_Load(object sender, EventArgs e)
       {
           Show show = new Show { ID = 1, Channel = 5, EpisodeTitle =
    "ASP.NET Databinding", ScheduledTime = new DateTime(2009, 4, 12, 12,
    0, 0), ShowTitle = "The C# Show" };
           Page.DataBind();
        }
  7. Change to the markup in the designer.

  8. The Text field gets the markup for the binding. We can just give it the property, like this:

    <asp:Label ID="Label1" runat="server" Text='<%# show.EpisodeTitle %>'></
        asp:Label>

This isn't the interesting way to bind things. It is nice because you can edit the binding without recompiling but the interesting way is in the C# code. Doing it in the C# code is much more readable and manageable. There are times to use each, but this is a C# book. The least we can do is to focus on the code-behind, right?

Data binding using the code-behind

Rather than set a property directly in the markup, we can set it equal to a value in the code-behind. For a repeating control, we can set a DataSource property in the C# code for the control. Then, when we bind the page, it uses that value to load in the right value or values from the code-behind.

Keep in mind, though, that with the Text property of a Label (for instance) this just simple data binding. I am just setting a value.

Let's try it with the earlier example. Just follow these steps:

  1. Keep the label text simple — just drop the Text property, like this:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Text.aspx.cs"
        Inherits="Chapter_3.Text" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://
        www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
    
            This is some text.<br />
            <asp:Label ID="Label1" runat="server" />
    
        </div>
        </form>
    </body>
    </html>
  2. In the code-behind, set the Text property equal to the property on the control that you want to bind to.

    Notice that there is no DataBind command for the page:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    namespace Chapter_3
       {
           public partial class Text : System.Web.UI.Page
           {
               public Show show;
               protected void Page_Load(object sender, EventArgs e)
               {
                   show = new Show { ID = 1, Channel = 5, EpisodeTitle = "ASP.
           NET Databinding", ScheduledTime = new DateTime(2009, 4, 12, 12, 0,
           0), ShowTitle = "The C# Show" };
                  Label1.Text = show.EpisodeTitle;
               }
           }
       }
  3. Run the application to see the value get set.

This works well, but remember, this is only simple data binding. It's just setting values. Full data binding is for controls with repeating properties.

Using commonly bound controls

After all this label stuff, let's talk about what data binding is really good for — collections. Data binding is great for dealing with groups of items, bound to repeating structures in HTML.

The typical example of data binding is the DataGrid control. If everything is set up correctly, you have remarkable control over how the grid looks. If things aren't named correctly, you still have the option to show all of the data in a default style. So let's get started. To create a databound grid, follow these steps:

  1. Add a new ASPX file to the projects called Grid.aspx.

  2. Change to design view.

  3. Open the Data section of the Toolbox and drag a GridView onto the design surface.

  4. Double-click the design surface to change to Code View and get a page load event handler.

  5. Make a mock collection of Shows in the page load event handler. I used a generic list of Show.

    List<Show> shows = new List<Show>();
    protected void Page_Load(object sender, EventArgs e)
            {
                shows.Add(new Show { ID = 1, Channel = 5, EpisodeTitle =
        "ASP.NET Databinding", ScheduledTime = new DateTime(2009, 4, 12, 12,
        0, 0), ShowTitle = "The C# Show" });
                shows.Add(new Show { ID = 2, Channel = 5, EpisodeTitle =
        "ASP.NET Styling", ScheduledTime = new DateTime(2009, 4, 12, 13, 0,
        0), ShowTitle = "The C# Show" });
                shows.Add(new Show { ID = 3, Channel = 8, EpisodeTitle =
        "Inheritance", ScheduledTime = new DateTime(2009, 4, 16, 9, 0, 0),
        ShowTitle = "Learning C#" });
    shows.Add(new Show { ID = 4, Channel = 8, EpisodeTitle =
      "Partial Classes", ScheduledTime = new DateTime(2009, 4, 17, 9, 0,
      0), ShowTitle = "Learning C#" });
             shows.Add(new Show { ID = 5, Channel = 8, EpisodeTitle =
      "Operator Overloading", ScheduledTime = new DateTime(2009, 4, 18, 9,
      0, 0), ShowTitle = "Learning C#" });
            }
  6. Add the datasource and the databind commands at the bottom of the page load.

    I have bolded the lines that I added in the code:

    List<Show> shows = new List<Show>();
        protected void Page_Load(object sender, EventArgs e)
        {
            shows.Add(new Show { ID = 1, Channel = 5, EpisodeTitle =
    "ASP.NET Databinding", ScheduledTime = new DateTime(2009, 4, 12, 12,
    0, 0), ShowTitle = "The C# Show" });
            shows.Add(new Show { ID = 2, Channel = 5, EpisodeTitle =
    "ASP.NET Styling", ScheduledTime = new DateTime(2009, 4, 12, 13, 0,
    0), ShowTitle = "The C# Show" });
            shows.Add(new Show { ID = 3, Channel = 8, EpisodeTitle =
    "Inheritance", ScheduledTime = new DateTime(2009, 4, 16, 9, 0, 0),
    ShowTitle = "Learning C#" });
            shows.Add(new Show { ID = 4, Channel = 8, EpisodeTitle =
    "Partial Classes", ScheduledTime = new DateTime(2009, 4, 17, 9, 0,
    0), ShowTitle = "Learning C#" });
            shows.Add(new Show { ID = 5, Channel = 8, EpisodeTitle =
    "Operator Overloading", ScheduledTime = new DateTime(2009, 4, 18, 9,
    0, 0), ShowTitle = "Learning C#" });
            GridView1.DataSource = shows;
            Page.DataBind();
        }
  7. Press <F5> to see the application run.

    As you can see in Figure 3-6, the columns from the database are all automatically bound to the HTML grid.

That's all well and good, but what if you don't want to show the ID, or want to put the columns someplace more to your liking? You can do that, too; it just takes a little more effort.

The capability of the gridview to automatically show all columns in a table is handled by a property: AutoGenerateColumns. The first thing we need to do is set that to False. This tells ASP.NET that we are going to set all of the columns by hand.

Next, we have to tell C# what columns we are using. This can be done in the ASP.NET code, but this is a C# book. Let's do it in the C# code.

We need to add two columns to the grid — let's say Channel and Episode. In order to do this, we need to define and set up two BoundColumn objects. Then we need to add them to the grid. That's what happens under the sheets when we add a datacolumn tag in the markup.

The TV schedule! Columns here are bound to the grid.

Figure 3-6. The TV schedule! Columns here are bound to the grid.

Here's the resulting markup. I bolded the lines of code that I added to the page load event handler:

List<Show> shows = new List<Show>();
   protected void Page_Load(object sender, EventArgs e)
   {
       shows.Add(new Show { ID = 1, Channel = 5, EpisodeTitle = "ASP.NET
Databinding", ScheduledTime = new DateTime(2009, 4, 12, 12, 0, 0), ShowTitle
= "The C# Show" });
       shows.Add(new Show { ID = 2, Channel = 5, EpisodeTitle = "ASP.NET
Styling", ScheduledTime = new DateTime(2009, 4, 12, 13, 0, 0), ShowTitle =
"The C# Show" });
       shows.Add(new Show { ID = 3, Channel = 8, EpisodeTitle =
"Inheritance", ScheduledTime = new DateTime(2009, 4, 16, 9, 0, 0), ShowTitle
= "Learning C#" });
       shows.Add(new Show { ID = 4, Channel = 8, EpisodeTitle = "Partial
Classes", ScheduledTime = new DateTime(2009, 4, 17, 9, 0, 0), ShowTitle =
"Learning C#" });
       shows.Add(new Show { ID = 5, Channel = 8, EpisodeTitle = "Operator
Overloading", ScheduledTime = new DateTime(2009, 4, 18, 9, 0, 0), ShowTitle
= "Learning C#" });

       GridView1.DataSource = shows;
       GridView1.AutoGenerateColumns = false;

       BoundField channelColumn = new BoundField();
       channelColumn.DataField = "Channel";
       channelColumn.HeaderText = "Channel";
       GridView1.Columns.Add(channelColumn);

       BoundField episodeColumn = new BoundField();
       episodeColumn.DataField = "EpisodeTitle";
       episodeColumn.HeaderText = "Episode";
       GridView1.Columns.Add(episodeColumn);

       Page.DataBind();
   }

Styling Your Controls

When you have the data in your controls, you need to get the control looking a certain way. There are a lot of options here. All the controls come with properties that can be set at design time and at runtime, or bound to cascading style sheets (CSS).

Being able to style is necessary; being able to manage the styles at runtime with C# is darn near magic. Using a combination of the three methods makes it possible to create dynamic applications that give the user the best experiences.

Setting control properties

By far, the simplest way to set style on a control is to use the built-in properties. It is straightforward, you know exactly what you are applying a look to, and IntelliSense helps you do so.

Notice I didn't say it was the "best" way to do styles. I said it was the simplest.

Setting control properties has a host of problems. If you have more than one control to set up, you have to set the properties on each of them — even if they are the same. The runtime has to handle a lot of extra stuff. Also, it makes your code messy.

Sometimes, though, you need to set a style this way. The best way to see them all is to check out the Properties panel. Set it to Categorized, and look the bottom, as shown in Figure 3-7. If you actually set properties here, they will be in the markup like the below example, not the code-behind, but you can at least find the names here.

<asp:GridView ID="GridView1" runat="server"
     onselectedindexchanged="GridView1_SelectedIndexChanged">
    <RowStyle BackColor="#FF6666" />
</asp:GridView>

After you get the name of something you want to set, you just set it like any other property:

GridView1.RowStyle.BackColor = System.Drawing.Color.Red;

The roughest part is discovering what framework element that the style will want as a value. The easiest way to determine this is to type the part to the left of the equal sign, and then mouse over the property to see how it is declared. BackColor, for instance, requires a System.Drawing.Color element. When I discovered that, I knew where to go to get the value.

Styles in the Properties panel.

Figure 3-7. Styles in the Properties panel.

Binding styles with CSS

Because we are in a Web application, using Cascading Style Sheets (CSS) seems like a good approach to handle our styles. Nearly every control in ASP.NET has a property — CssClass — that takes advantage of the styles loaded as part of the project.

To get started, you need a few CSS classes, which are not the same as .NET classes. A class in CSS is a collection of styles that can be connected to a collection of markup, so as to match the properties that can be matched between them. To bind styles with CSS, follow these steps:

  1. Right-click the project and select Add New.

  2. Select Style Sheet from the dialog box.

    I named mine Chapter3.css.

  3. When the style sheet comes up, right-click the CSS Outline and select Add Style Rule.

  4. In the element dialog box, select Class Name and type GridViews in the text box.

  5. Click the right arrow button as shown in Figure 3-8.

  6. Press OK, and notice the new entry in the style sheet.

Adding a style sheet class.

Figure 3-8. Adding a style sheet class.

Just for demonstration, I added a few things to the style sheet.

body
{
}
.GridView
{
   font-family:French Script MT;
   background-color: Fuchsia;
}

To bind this to the control, we use the CssStyle property, which accepts the class in the CSS file. Link the CSS file to the page in question in the page markup first, using the "link" snippet in the ASP.NET markup (remember to put it in the <head> tag section).

In the code-behind, just set the CssStyle property like you would any other property, like this:

GridView1.CssStyle = "GridViews";

Making Sure the Site Is Accessible

When I say accessible here, I am not talking about the server being up. I am talking about making sure the controls you use are available to people who have disabilities, such as diminished senses of sight, hearing, or touch. Such people have a different browsing experience than you or I.

Microsoft has made a significant investment in accessible Web browsing, and you'll be pleased to find that most of the controls make good decisions about accessibility right out of the box. Understanding how to use them for this purpose takes a little effort, however.

If you are building Web sites for large enterprises or the government, Section 508 (an amendment to the Rehabilitation Act) makes this very important. Check out www.section508.gov for more information.

Control features for accessibility

Most ASP.NET controls, where applicable, fit a certain feature list for accessibility. The goal is to make coding for accessibility easy for the programmer and functional for the user.

  • Any element that isn't made of text should have an alternate text option. For instance, all image tags support an AlternateText property, which populates the HTML alt tag. Web-to-text readers will "speak" the contents of this tag in place of the image. If you add an Image to a Web page, Visual Studio even prompts you for the alternate text.

  • Controls don't require the use of style sheets or color dependency. If you wish, it is easy to strip all style information from a page for simplicity of use by a reader or a low-sight version of the application.

  • All input controls in Getting Input from the User support a TabIndex property, which allows users to tab from control to control. For those not using a mouse, this is optimum.

  • Setting which part of the form has the cursor by default (called default focus) is easy in ASP.NET with the DefaultFocus property. Changing it is easy with the SetFocus method.

  • Buttons can get keyboard equivalents using the AccessKey property.

  • Labels and input controls can be associated, which many Web readers depend on.

Design considerations

The principle design consideration for accessibility is to use the features. Set the alternate text. Use the tab indexing. Set a default focus. Make your application easy to use for everyone.

There is a new feature in Visual Studio 2010 called Check Page for Accessibility, which checks WCAG and Section 508 errors. If you use this feature, warnings will actually be posted to your build process.

Constructing User Controls

Have you ever been to a site with a three-part U.S. phone number shown as three textboxes? You can usually automatically tab between them, and this structure makes sure you have exactly the right number of digits in each text box. That's something that you might very well use on every page of many applications, right?

That phone number control consists of things that we already have around us: text box controls, client-side scripting, and validation. All that you need is to put them together.

The technology that you use to combine existing controls in useful ways is called a User Control, or ASCX. ASCX is encapsulated, easy to create, and easier to use.

Making a new phone number user control

To show you what I mean, here I show you how to make my favorite user control, the Phone Number control. In this incarnation, it is only good for U.S. format, but that's okay. It gets the point across. Just follow these steps to create a phone number control:

  1. In the Web project we have been using in this chapter, right-click the project file, and choose Add

    Making a new phone number user control
  2. Select Web User Control. (See Figure 3-9.)

    I named it PhoneNumber.ascx.

    Adding the Phone Number control.

    Figure 3-9. Adding the Phone Number control.

  3. Switch to Design view.

  4. Drag three text boxes to the designer, next to one another. If you want to get fancy, put hyphens between them.

  5. In the Properties panel, set the MaxLength for the first two text boxes to 3 and the last one to 4. This prevents the user from putting too many characters in a field.

  6. Right-click the designer and select View Code.

  7. Add a property to the code-behind that allows a page using the control to get to the phone number.

    The goal is to get all the content from the controls, patch it together, format it, and deliver it as a public property. Here is the code:

    private string _phoneNumber;
    public string PhoneNumberValue
    {
        get
        {
            _phoneNumber = string.Format("({0}){1}-{2}");
            return _phoneNumber;
        }
    }

So now we have a control — just like the controls in the Toolbox — that accepts a phone number in pieces and formats it nicely. Let's play with it.

Using your new control

You'll love using this control. It really does work just like a Toolbox control. Follow these steps to see how it works:

  1. Right-click on the project, and add a new Web file.

    I named mine UseThePhoneNumber.aspx.

  2. Change to the design view.

  3. Drag the ascx control right from the Solution Explorer onto the design surface.

    Ta da! The control shows up just like a plain text box would, but it is just like we formatted it. Check out Figure 3-10.

    The Phone Number control.

    Figure 3-10. The Phone Number control.

  4. Add a label and a button to the form. Try to fill out the control, click the button, and see the formatted phone number.

  5. Double-click the button to get an event handler for the click event. Add some code to populate the label on the button click, like this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    namespace Chapter_3
    {
        public partial class UseThePhoneNumber : System.Web.UI.Page
        {
            protected void Button1_Click(object sender, EventArgs e)
            {
                Label1.Text = PhoneNumber1.PhoneNumberValue;
            }
        }
    }
  6. Right-click on the ASPX page and set it as the start page.

  7. Press <F5> and run the application. Enter a phone number in the control and click the button.

    The formatted phone number should appear in the label.

This is a boring example, but you can see how this can be used to collect commonly used fields together for reuse in an application. Order details, addresses, and map coordinates, among other types of information, all are usually grouped together and make great user controls. In a travel application I recently worked on, the start city and date and the end city and date became user controls. It's a great way to solve simple reuse problems.

Adding Custom Controls

Beyond the scope of a user control is a control that — perhaps — no one has thought of before. Maybe your company makes a device with a pressure gauge that you need to replicate in code. Or perhaps you need to display a unique set of patient statistics on a monitor, or demonstrate the running of some data engine.

Those kinds of controls call for the next level: custom controls, sometimes called server controls. A custom control is a Web control built using essentially the same tools that Microsoft used to build the controls that we have used throughout this chapter.

I won't fool you — building a server control is nontrivial. To get one started, you need a whole new project, not just a new file. The project type is a Server Control project, and it gives us a whole battery of code to start with, much like this:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace NewServerControl
{
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
    public class ServerControl1 : WebControl
    {
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public string Text
        {
            get
            {
                String s = (String)ViewState["Text"];
                return ((s == null) ? "[" + this.ID + "]" : s);
            }

            set
            {
                ViewState["Text"] = value;
            }
        }

        protected override void RenderContents(HtmlTextWriter output)
        {
            output.Write(Text);
        }
    }
}

One property and one method appear in the default configuration. A server control is basically just text output to the screen. It causes markup, just like a Label control emits a set of <span> tags. If you want this control to emit a set of <div> tags, you just change the property get statement.

For more information about making good controls, search for Server Control in MSDN. There are a number of good articles, and anything from ASP.NET 2.0 or later works just fine.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.88.165