C# .NET Programming Tip: Using the Tag property of controls

I’ve been doing C# programming at my job lately. Throughout the process I’ve hit a few little walls that were difficult to find answers for and thought writing down the solutions here would be good for myself any anyone who happens to find this by-way-of search engine. So as I come upon these little bits of useful harder-to-find information, I’ll write something here about it.

Creating windows form controls programmatically and passing data between class instances was one such issue. I did a number of searches on Google and didn’t really find much help. The main suggestion was to create an EventArgs class that passes events or some such thing. That was a really involved process that didn’t seem like it was worth the effort to implement.

I then created my own static global event class where anything in the program could pass an unlimited number of parameters. Once the parameters were accessed, they were deleted from the static Dictionary that stored everything. Well actually it was a Dictionary inside a Dictionary (parameterSetName -> (Dictionary that holds all parameters)). So it was a one shot wonder.

Let me give a little background information about why I needed to implement it:
I had a number of classes that generate their own windows controls to select or edit themselves. For example, A “checklist container” created controls to allow the user to select one specific checklist. The function was called with a reference to a FlowLayoutPanel. Then when the user clicked a button to select one specific checklist, the container class would call a function inside the selected checklist instance to tell it to display edit controls for itself. The problem was passing that FormLayoutPanel reference to the checklist function from an event function that I linked to the buttons that were dynamically generated.

There was really no easily noticeable way to do it. Every button the Container class created was all linked up into one Event function. The way .NET works is that you can create your own event function, but only two specific parameters are passed (one is the control itself, in the sender parameter).

So that is why I created that static global parameter class. The thing is I ran into another roadblock that made the global parameter class useless. The way I designed it is that the parameters were deleted from the Dictionary object once some function accessed them, but what if I wanted a form that did a similar process, but did not completely replace the current controls with something new (eg: the single checklist edit controls needed to perform actions like reading data from textboxes that were created at runtime. The function that would take events from the buttons on the edit form had no way of accessing textboxes at this point.

I go back on Google and Yahoo! and do a few more searches. This time I come upon the Tag property of Windows Form Controls. It’s an object variable that you can put anything into and it works perfectly for what I was trying to do.

By this point you probably are having a hard time understanding what I am talking about. So here are a few code examples to help you out:

The way my program works is that checklist has multiple checklist items and each checklist item has a few windows form buttons that should do things.

This is a button that would fire off a request to update a database data from a textbox:

Button btnNotesChance = new Button();
btnNotesChance.Text = "Update Notes";
btnNotesChance.AutoSize = true;
pnlTxtBoxes.Controls.Add(btnNotesChance);
btnNotesChance.Name = "clintsbx-" + i.ToString(); //save a name so we can know who calls the event handler
btnNotesChance.Tag = txtNotes; //save the handle to the notes textbox into the button's "tag" variable
btnNotesChance.Click += new EventHandler(displayChecklistAsControls_Event);

Notice the Name property. I give it a unique identifier clintsbx-#, so that way I can know which “Update Notes” button was clicked in the function displayChecklistAsControls_Event. I’ll get to the event function later. Also notice the Tag property. That stores the handle to the button’s related TextBox “txtNotes” object (windows form textbox). So now when the button is clicked we will know who called the update and what textbox to take the information from!

Here is an excerpt from the event function:

//event handler for the checklist selector buttons
private void displayChecklistAsControls_Event(Object sender, EventArgs e) 
{
    //fetch the calling control
    Control senderControl = (Control)sender;

    //take the calling control's name and split it up into two parts, one means the type of control and the other means
    //the index of the control (eg: ollststatu-4 means the 4th listbox for checklistitem status)
    string [] nameData = senderControl.Name.Split(Convert.ToChar("-"));

    //turn the second array value into an integer
    int itemSelected = Convert.ToInt32(nameData[1]);

As you can see there the sender variable is key. We can use that to get access to the button that called the event. Then we can take the Name of the control and the Tag of the control and do what we need to do.

I perform a Switch on the first nameData item to decide which set of controls called the event. Here is some code below for “update notes” I have been talking about.

case "clintsbx":
//take the notes textbox data and save it to the corresponding checklistitem notes field
//utilizes the button's tag element to save a reference to the corresponding textbox
string selectedItemText = ((TextBox)((Button)senderControl).Tag).Text;
//only update if the user made some type of change
if (checkListItems[itemSelected].Notes.Equals(selectedItemText) == false)
{
    //update the instance and database with this text data
    checkListItems[itemSelected].Notes = selectedItemText;
}
break;

It takes the button’s Tag property and turns that into a reference to the textbox. Then it is able to access the Text property of the textbox and then update the database.

Problem solved!


Posted

in

by