ASP.NET/C#: Magic Menu Web App: Part Three

Welcome to episode three of our series on the “Magic Menu” web app – the C# code!

Please check out part two before we begin if you like.

Default.aspx.cs

We start out by importing a standard set of namespaces, which generally hold tons of standard .NET classes we may want to use within the rest of our code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;

Next we define our class, which by default is called…_Default! Our class is public which means this class can be accessed by any other class in our app. Our class is also partial, which means code is stored in multiple files for the class, because web pages for web apps in .NET generate extra design code that we do not see and is stored elsewhere. After the colon we see System.Web.UI.Page which indicates we are inheriting from the this standard .NET class.

public partial class _Default : System.Web.UI.Page
{
...

Inside of our class, we have two event handling methods, and one regular method.

Our first event handler is called Page_Load. This method is an interesting one because when it is defined in a class with the correct parameters, it automatically is run on event of the load of a web page. This method is protected, which means members of this class or other classes that inherit from this class are the only ones who can access this method. The two parameters this method accepts are sender which identifies the control that triggered this event, in our case our web page, and e which is any additional information our web page wants to send along to this event handler.

protected void Page_Load(object sender, EventArgs e)
{
...

Inside of Page_Load, we have the code that will initialize our form data. To ensure this only happens once, and not each time the page is re-run (to avoid possible issues like adding more items to a drop-down list), we check to see if the Page class property (referenced by this) IsPostBack is false.

if (!this.IsPostBack)
{
...

Now we get into a lot of code that basically assigns values to the various web controls in the web app. For example, lstBackColor.Items.Add("White"); accesses the Items property of the DropDownList web control lstBackColor which stores the values of the drop-down list, and uses a method called Add to add a value of “White” to the drop-down list. It should be noted that this web app was built while studying the book “Beginning ASP.NET 4 in C# 2010” (MacDonald, Matthew. Beginning ASP.NET in C# 2010. USA: Apress, 2010) and uses similar concepts as a sample in the book, as well as some of its code bits and conventions. This particular section is very close to that of the book.

A little way down we happen upon something interesting when setting border options. Borders in .NET are represented in an enumeration, which is a set of integer constants, like a number that represents a specific border style, with descriptive name references, like “Double”. The idea is that referencing “Double” is easier than remembering what the specific number is for a border style.

So for our border radio buttons, we’ll make use of both parts of the BorderStyle enumeration. Our label will use the descriptive name, and we’ll assign the integer portion as the value of the radio button. To do this, we first need to create a new ListItem object which is a class used to create objects for various List controls, such as drop-down items for DropDownList and in this case radio buttons for RadioButtonList.

We access the BorderStyle enumeration to get the labels of our border style and assign it to the Text property of our new ListItem object (think the text that sits with the radio button <input> tag to represent the label). Then we assign the integer value from the enumeration (converted to a string first) to the Value property (the value attribute of our radio <input>). We also see some casting here which is basically converting one data type to another without changing the actual data type of the object, think of it as temporarily, usually as part of an assignment to something else. This casting code (int)BorderStyle.None converts the None value of the BorderStyle enumeration to an integer for use in assigning the value of the radio button.

Lastly we ensure the first option in the DropDownList is selected initially, by assigning the SelectedIndex property of the ListItem object to be 0.

// Set color options
lstBackColor.Items.Add("White");
lstBackColor.Items.Add("Teal");
...
// Set border style options
ListItem item = new ListItem();

            item.Text = BorderStyle.None.ToString();
            item.Value = ((int)BorderStyle.None).ToString();
            lstBorder.Items.Add(item);

            item = new ListItem();
            item.Text = BorderStyle.Double.ToString();
            item.Value = ((int)BorderStyle.Double).ToString();
            lstBorder.Items.Add(item);

            item = new ListItem();
            item.Text = BorderStyle.Solid.ToString();
            item.Value = ((int)BorderStyle.Solid).ToString();
            lstBorder.Items.Add(item);

            lstBorder.SelectedIndex = 0;
        }
...

Next up, the event handler cmdUpdate_Click, which is evoked when we click on the Update button.

Here is where I added in a little tracing code, to see what action was taking place with my program, which would be useful for tracing what happens to data or figuring out a bug for example. I commented it out for now after seeing how that works.

The next few lines assign the background and foreground colors as well as font style to the main Panel web control where the “Magic Menu” resides. For example we assign the BackColor property of pnlMenu a color which is determined by taking the option chosen in lstBackColor and then passing it as a parameter to the FromName method of the standard Color class. This will pull the color from the “name” – i.e. “White”, that is selected.

Much later in the method we have code that takes the numeric value for the border radio button selected and passes it as a parameter to the standard Int32 Parse method to turn the string into an integer. This gets assigned to a variable borderValue. Then we cast this variable as a BorderStyle before assigning it to be border style of the panel.

protected void cmdUpdate_Click(object sender, EventArgs e)
    {
        // if tracing is required
        //Trace.IsEnabled = true;

        // Update the color
        pnlMenu.BackColor = Color.FromName(lstBackColor.SelectedItem.Text);

        pnlMenu.ForeColor = Color.FromName(lstFontColor.SelectedItem.Text);

        // Update the font
        pnlMenu.Font.Name = lstFontName.SelectedItem.Text;
...
        int borderValue = Int32.Parse(lstBorder.SelectedItem.Value);
        pnlMenu.BorderStyle = (BorderStyle)borderValue;

The remaining code in our event handler applies some exception handling. We “try” some code and it doesn’t work out, we “catch” the error and deal with it. In this case we are ensuring the user does not enter a font size smaller than zero. They may enter something way too large to really fit the “Magic Menu”, but that’s okay for this example.

Inside of our try block, we try to assign the font size for pnlMenu the value returned by our third and final method in this class, validFontSize. We pass the size of font entered by the user to this final method.

Notice validFontSize is defined to return a value that is an int. It also accepts the int which represents the font size, and checks if it is greater than 0. If it is, then it’s all good, and it returns this value to be assigned as the font size of the pnlMenu. Back in our try block, we write a positive message to a label in another panel in our web app called pnlException, and also make this message green in color. If the user enters a number less than 0, then we create a new error object of type ArgumentOutOfRangeException, and pass it the name of the parameter that was passed to validFontSize and a custom error message for the user.

Our catch block is passed our error and then a longer custom error message is written to the label in the panel using properties of this error we assigned back in validFontSize as well as more system information on the error stored in the StackTrace property. We also make the color of this overall message red.

    // Add exception handling for invalid font size of 0
        try
        {
            pnlMenu.Font.Size = validFontSize(Int32.Parse(txtFontSize.Text));
            lblFontSizeException.Text = "<b>Excellent!</b>";
            lblFontSizeException.Text += "<br /><br />";
            lblFontSizeException.Text += "The font may possibly be too big for the menu, but this is indeed a valid font size choice because it is greater than 0.";
            lblFontSizeException.ForeColor = System.Drawing.Color.Green;
        }
        catch (ArgumentOutOfRangeException err)
        {
            lblFontSizeException.Text = "<b>Please try again.</b>";
            lblFontSizeException.Text += "<br /><br />";
            lblFontSizeException.Text += "<b>Message:</b> " + err.Message;
            lblFontSizeException.Text += "<br /><br />";
            lblFontSizeException.Text += "<b>Source:</b> " + err.Source;
            lblFontSizeException.Text += "<br /><br />";
            lblFontSizeException.Text += "<b>Stack Trace:</b> " + err.StackTrace;
            lblFontSizeException.ForeColor = System.Drawing.Color.Red;

            Trace.Warn("cmdUpdate_Click", "Error: Data entered is out of bounds.", err);                        
        }
...
 protected int validFontSize(int newFontSize)
    {
        if (newFontSize > 0)
        {
            return newFontSize;
        }
        else
        {
            ArgumentOutOfRangeException err = new ArgumentOutOfRangeException("newFontSize","Font size must be greater than 0.");
            throw err;
        }
    }
}

What results when the user enters a negative font size will be a message similar to the following:

Please try again.

Message: Font size must be greater than 0. Parameter name: newFontSize

Source: App_Web_4tahcmph

Stack Trace: at _Default.validFontSize(Int32 newFontSize) in [path to file]\Default.aspx.cs:line 99 at _Default.cmdUpdate_Click(Object sender, EventArgs e) in [path to file]\Default.aspx.cs:line 67

Let’s squeeze in mention of the magic_menu.css file, which shows how you can add your usual CSS styles to HTML elements of the web app if you wish. One example is by accessing the id of the web control, like #pnlException. Some styles however are defined and stored directly on the web controls and thus are not included in our CSS file, such as the width and height.

Here is a jQuery version of “Magic Menu”, to give you an idea of how it works. The exception handling is not as extensive as the ASP.NET/C# version, but it basically looks and functions the same. In the near future I will write a post explaining how it was built.

jQuery Magic Menu

This concludes our series on the “Magic Menu” web app, hope you enjoyed it and learned a little along the way about ASP.Net, C# and object-oriented programming! In writing this for you, I certainly refreshed my memory and understanding of the subjects. Until next time!