Determine Subroutine Click Event Trigger

Using one sub-routine to handle more than one link button click event requires determination of which button click triggered the sub-routine.

I had an existing subroutine handling a link button. Examining the entries in a form, updating a database and sending an email. A second button was required on the form which would update the database but not send the email.

Options were:

  1. Clone the sub-routine omitting the email sending
  2. Two subroutines to handle the click events with each calling a common function where the difference between the two actions is to be determined. Or just the common block of code for saving the form values.
  3. One subroutine to handle the two click events with the email sending determined by which link button was clicked.

For a quick solution I chose option 1 – clone the subroutine.

However, with time available later I was interested in implementing option 3 – one subroutine handling two click events with a part of the code in the subroutine determined by which link button triggered the event.

In the code below the two link buttons are declared, followed by an outline subroutine to handle the clicking of the two buttons.

'Declare two link buttons with event handling
Dim WithEvents cmdSave as System.LinkButton
Dim WithEvents cmdAdd as System.LinkButton'Sub routine to handle the clicking of either button.
'Run common block of code in sub routine
'Determine event was triggered and run an optional block
Private Sub cmdLButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSave.Click ,
  'common block of code here (update database)
  'Code here specific to one item
  If sender = cmdAdd  Then
    'send email to applicant confirming form submission
  End If
  If sender = cmdSave Then
    'send email to applicant confirming form submission
  End If
End Sub

A test is made to determine which of the two link buttons was clicked.

In the example above I have shown each as their own separate if statement. When I developed this further I replaced the if statements with a select.

Shown below is a part of the updated

missing the right buttons/commands, would be better to base this upon the GridView edit/update/delete automation

 <asp:GridView ID="gdvCU" runat="server"
    <asp:TemplateField ItemStyle-HorizontalAlign="left" ItemStyle-Width="80%">
        <asp:RadioButton ID="rbnOption" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.Text")  %>' GroupName='<%# DataBinder.Eval(Container, "DataItem.Value")  %>' Checked='<%# DataBinder.Eval(Container, "DataItem.Selected")  %>' AutoPostBack="true" OnCheckedChanged="DeselectSelected" />
    <asp:TemplateField ItemStyle-HorizontalAlign="Left" ItemStyle-Width="20%">
        <asp:LinkButton ID="cmdCU" runat="server" Text="Send" CommandName='<%# DataBinder.Eval(Container, "DataItem.Value") %>' CommandArgument='<%# DataBinder.Eval(Container, "DataItem.Value") %>' CausesValidation="false" Visible='<%# DataBinder.Eval(Container, "DataItem.enabled")  %>'></asp:LinkButton>
        <asp:Label ID="FruitId" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.FruitId") %>' Visible="false"></asp:Label>

The Associated subroutine to handle the above gridview and its submission.

Protected Sub cmdCURegister(ByVal sender As Object, ByVal e As GridViewCommandEventArgs) Handles gdvCU.RowCommand
      Select Case e.CommandName
        Case "Registered"
          'action here if visitor is registered
        Case "NotRegistered"
          'action here if visitor is not registered                      
      End Select
    End If

  Catch exc As Exception 'Module failed to load
    ProcessModuleLoadException(Me, exc)
  End Try
End Sub

What about option 2?

Having satisfied my interest with the common subroutine with a test to determine the source and choose the appropriate action I never implemented option 2.

Converting to and from ASCII with

The ASCII table is a representation of the Roman characters as numeric values. Given an ASCII value we may wish to convert it to its corresponding character, or indeed back the other way from character to ASCII value.

To convert an integer variable of ASCII value, myASCII, to a string we use:

myString = char(myASCII)

and to convert back the other way, from a character to the ASCII value, we use

myASCII = asc(myString)

For the ASCII table of characters see the article: ASCII Table of Numbers and Characters.

Convert Textbox String to Double

The task is to take user entered textbox content, converting it to a field of type double.

As a part of a form I had a numeric entry field. The string value entered in this textbox to be converted to type double for saving in a database.

The public view of the textbox included the appropriate numeric validation. However, I prefer to test the entered content rather than assuming that this protection will be sufficient.

Given below is the text box definition.

<asp:TextBox is=”price” Visible=”True” runat=”Server />

I found that my old test for reading the value in a textbox and assigning it to a variable of type double had become unreliable.

To ensure the textbox string is correctly converted to a double, set the value to 0 if empty, or if it’s value doesn’t qualify as a double. I used the following:

Dim d as Double
If Double.TryParse(tbxPrice.Text, d) Then
  Price = convert.ToDouble(tbxPrice.Text)
  Price = 0
End If

In the example above I first test to see if the content will convert to type double. If this works then we are good to make the conversion.

If the trial conversion fails then set the value to 0.

Whilst it’s possible to add checks to ensure that field values are of the correct type prior to submission I like to also add a check of the data when handling too. You can’t be too careful.

LinkButton Handles OnClick Equivelent in C#

To handle a Linkbutton onclick in VB.NET the LinkButton is declared and a handler sub declared:

<asp:linkbutton id="cmdAdd" runat="server" ResourceKey="Add" BorderStyle="none" CausesValidation="true" />

Private Sub cmdAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdAdd.Click
End Sub

C# doesn’t support the handles on click, the function is simply declared.

The LinkButton declaration is given below. Unlike there is no WithEvents part of the declaration.

protected global::System.Web.UI.WebControls.LinButton cmdAdd

Explanations of the above:

  • protected – Used to restrict access to the code to the same class.
  • global – Used to clarify that the object is taken from the global namespace as opposed to the current one.
  • :: – This operator, positioned between two indentifiers, is used to look up an identifier.
  • cmdAdd – name of the LinkButton

Looking in the .ascx presentation file the link button is declared as:

<asp:linkbutton id=”cmdAdd” runat=”server” ResourceKey=”cmdAdd” CausesValidation=”true” />

Begin the OnLoad, and include reference for the LinkButton

protected override void OnLoad(EventArgs e) {
try { += new System.EventHandler(cmdAdd_Click);

Then later in the code there is the cmdAdd_Click function:

private void cmdAdd_Click(System.Object sender, System.EventArgs e) {try {
// actions here for the function



MSDN: global

MSDN: The :: Operator

MSDN: How to: Use the Global Namespace Alias


Add an Edit Button to a DataGrid

The DataGrid configuration includes an editColumn, allowing inline editing of the row.

An edit button can be added to a DataGrid using the editColumn feature.

With the addition of the edit column, links are added to handle the usual actions of edit, update and delete.

Associated with the editColumn components are event handlers in the code behind to handle these actions.

When the DataGrid row is in the default mode the column item shows the word (or button dependant upon link type) Edit.

Clicking on the edit link changes the row into edit mode. Converting items into text boxes and changing the link edit to the two links Update and Delete.

To add an edit Button to a DataGrid add code to the following:.

  • In the DataGrid header
  • In the column definitions of the DataGrid add another column
  • In the code behind add an event handler for the edit button
  • In the code behind add an event handler for the update button
  • In the code behind add an event handler for the cancel button
  • Ensure that the postback is handled correctly

DataGrid Header

To handle the additional edit events details are added to the DataGrid header.

<asp:datagrid id="grdTeam"

Shown below are the column definitions of the DataGrid:

<asp:EditCommandColumn buttontype=”LinkButton” UpdateText=”Update” cancelText=Cancel” EditText=”Edit”></asp:EditCommandColumn>

<asp:datagrid id="grdTeam" Visible="False" GridLines="None" runat="server" AutoGenerateColumns="False"
    cellpadding="4" Borderwidth="0" bordercolor="transparent" width="400px" AllowPaging="True"
    <EditItemStyle BackColor="#eeeeee" />
    <AlternatingItemStyle BackColor="#cccccc" />
    <ItemStyle Font-Size="10px" Font-Names="Verdana" HorizontalAlign="Left" BackColor="WhiteSmoke" />
    <HeaderStyle CssClass="datagridheader" />
    <PagerStyle CssClass="datagridPage" Mode="NumericPages" />
        <asp:TemplateColumn HeaderText="Name">
                <asp:Label runat="server" Visible="true" Text='<%# DataBinder.Eval(Container, "") %>' ID="Name" />
                <asp:Label runat="server" Visible="false" Text='<%# DataBinder.Eval(Container, "DataItem.TeamId") %>' ID="TeamId" />
                <asp:TextBox runat="server" Columns="15" Text='<%# DataBinder.Eval(Container, "DataItem.Name") %>' ID="Name" />
                <asp:Label runat="server" Visible="false" Text='<%# DataBinder.Eval(Container, "DataItem.TeamId") %>' ID="TeamId" />
        <asp:EditCommandColumn Visible="True" ButtonType="LinkButton" UpdateText="Update" CancelText="Cancel" EditText="Edit" />
                <asp:LinkButton runat="server" ID="Delete" Text="Delete" CommandName="Delete" CausesValidation="false" Visible="true" />

Edit button event handler

When the edit button is clicked the row is to change to show the update and cancel options.

The row has an index value given by e.Item.ItemIndex.

The index value is assigned to the DataGrid parameter EditItemIndex.

Having set the index for the edit item the DataGrid is bound once more. This time the selected row will be in edit mode, displaying the update and cancel buttons.

Shown below is the subroutine MyDataGridEdit which is handling these actions.

Sub onEditCommand(ByVal sender As Object, ByVal e As DataGridCommandEventArgs)
	grdTeam.EditItemIndex = e.Item.ItemIndex
 Catch exc As Exception 'Module failed to load
	ProcessModuleLoadException(Me, exc)
 End Try
End Sub 'doEditCommand

Delete button event handler

To delete an entry the index reference for the row is passed to a subroutine.

Within the delete subroutine the entry reference ID (TeamId) is obtained from a hidden element within the row.

As can be seen there is a test to ensure that the row isn’t in edit mode.

Sub onDeleteCommand(ByVal sender As Object, ByVal e As DataGridCommandEventArgs)
	If grdTeam.EditItemIndex = -1 Then
	   Dim objITeam As New TeamInfo
	   Dim objCTeam As New TeamController
	   objCTeam.DeleteTeam( CType(e.Item.FindControl("TeamId"), Label).Text)
	End If
 Catch exc As Exception 'Module failed to load
	ProcessModuleLoadException(Me, exc)
 End Try
End Sub

Cancel button event handler

If the cancel button is clicked the DataGrid is to revert to the normal view.

In this example the EditItemIndex is effectively unset and the DataGrid once again is rebound using the subroutine BindDataGrid.

Sub onCancelCommand(ByVal sender As Object, ByVal e As DataGridCommandEventArgs)
	grdTeam.EditItemIndex = -1
 Catch exc As Exception 'Module failed to load
	ProcessModuleLoadException(Me, exc)
 End Try
End Sub 'doCancelCommand

Code behind update button event handler

If we are in edit mode and the update button is clicked then this entry is to be updated.

The update subroutine is called, in this instance myDataGridUpdate.

In this example the reference id for the data entry has been stored as a hidden entry in the row. The first table cell has been used.

Sub onUpdateCommand(ByVal sender As Object, ByVal e As DataGridCommandEventArgs)
	If e.CommandName = "Update" Then
	   Dim objITeam As New TeamInfo
	   Dim objCTeam As New TeamController
	   objITeam.Name = CType(e.Item.FindControl("Name"), TextBox).Text
	   objITeam.TeamId = CType(e.Item.FindControl("TeamId"), Label).Text
	End If
	grdTeam.EditItemIndex = -1
 Catch exc As Exception 'Module failed to load
	ProcessModuleLoadException(Me, exc)
 End Try
End Sub

Below I include

Private Sub BindData()
	Dim objITeam As New TeamInfo
	Dim objCTeam As New TeamController
	grdTeam.DataSource = objCTeam.GetTeamList(ModuleId, PortalId)
	grdTeam.Visible = True
 Catch exc As Exception 'Module failed to load
	ProcessModuleLoadException(Me, exc)
 End Try
End Sub

Adding Tooltips to Datagrid Rows

Adding a tooltip to a DataGrid row can provide additional information about the entry. The space available within the pop-up is likely larger than that within the row cell.

The tooltip allows for a minimal presentation on the DataGrid rows, ensuring that the information presented is succinct and easy to follow.

I like to use the ItemDataBound event handler to add tooltips to DataGrid rows. This allows more control over the content.

The DataGrid layout structure is defined in the in the .ascx file. Columns and rows are defined with references to the database fields.

Shown below is the DataGrid definition in the .ascx file.

<asp:datagrid id="grdFruit"
<asp:TemplateColumn HeaderText="Status" HeaderStyle-CssClass="subhead">
<asp:Label id="RefId" Text='<%# DataBinder.Eval(Container,"DataItem.RefId") %> ' Visible= "False" runat= "server" Visible="False"></asp:Label>
<asp:Label id="Name" Text='<%# DataBinder.Eval(Container, "") %> 'runat="server"></asp:Label>

In the associated code behind file, functions exist to bind the DataGrid to the database and to perform an action when each row is bound: ItemDataBound.

Dependant upon the implementation and the relevant clauses, the tooltip content may either be derived within the ItemDataBound function or derived on the SQL and stored as a hidden field.

I often have a column where I sneak these hidden items in, a status column is a good one. Note the row below where the value of the id is taken from the database.

The value of the reference, RefId, to be used for our tooltip, therefore ensures that it is available in the column definitions.

Considering the code behind file .ascx.vb. A sub-routine is required to handle the ItemDataBound event of the DataGrid and that the handling of row highlighting is working.

Following the addition of the events for the row colours we need to add one more for our tooltip.

Private Sub grdFruit_OnItemBound(ByVal sender As Object, ByVal e As DataGridItemEventArgs) Handles grdFruit.ItemDataBound
    If (e.Item.ItemType = ListItemType.Item) Or (e.Item.ItemType = ListItemType.AlternatingItem) Then
      e.Item.Attributes.Add("onclick", "javascript:window.location.href='" & EditUrl("RefID", CType(e.Item.FindControl("RefId"), Label).Text, "Edit_short") & "'")
      e.Item.ToolTip = "Ref: " & CType(e.Item.FindControl("RefId"), Label).Text
    End If
  End Try
End Sub

The table below is an example of the results from the above.


In this example hidden fields were added to the DataGrid rows. These fields were then used when adding the tooltips to the row during the OnItemBound process.

Adding Auto Change to a DropDownList

Adding an onchange to a drop down list enables other fields on the page to be updated dependant upon the selection.

I have used the auto post back on a drop down list to:

  • create a cascading drop down list. The selection of the parent item governs the entries in the child list
  • a page size selection changing the number of rows shown in a GridView

Taking the GridView page size as an example.

For a table of items, with paging, either a fixed page size can be used. Or the option may be given to select the page size for the table of results. This allows the number of results in the table to be selected according to the display.

Giving the option to change the page size requires that the results be re-sourced from the database and the paging reset to the first page.

A refresh button could be provided, perhaps positioned alongside the paging, which is an update of the table results displayed. Or as implemented in this example, changing the selection of the dropdownlist of page sizes causes a refresh of the page implementing the updated number of table rows shown and resetting the page counter to the first page.

This example is taken from work for a DotNetNuke website.

A page size selection was added to a table of entries. Changing the page size caused a refresh of the page with a change to the number of rows displayed in the table.

To implement this auto post back there are three additions to be added:

  1. a WithEvents to the DropDownList object
  2. an autopostback to the dropdownlist itself
  3. a handler for the autopostback

Addition of WithEvents

In the declaration add WithEvents, giving:

Protected WithEvents ddlPageSize As System.Web.UI.WebControls.DropDownList

The addition of the WithEvents adds the necessary JavaScript to the page to facilitate the handling of the drop down list onchange event.

Auto Postback

For the DropDownList add the parameter AutoPostBack=”True”

Adding the autopostback parameter to the drop down list adds the code to cause the postback when a change is made to the selection.

In the example below the DNN label is shown followed by the declaration for the drop down list. The list shows a number of different page sizes. Nor that the autopostback has been added with a value of true, enabling it.

<dnn:label id="plPageSize" suffix="" runat="server" controlname="ddlPageSize" ></dnn:Label>
<asp:DropDownList id="ddlPageSize" Runat="server" AutoPostBack="true" >
  <asp:ListItem Value="5" Text="5"></asp:ListItem>
  <asp:ListItem Value="10" Text="10"></asp:ListItem>
  <asp:ListItem Value="15" Text="15"></asp:ListItem>
  <asp:ListItem Value="20" Text="20"></asp:ListItem>
  <asp:ListItem Value="30" Text="30"></asp:ListItem>
  <asp:ListItem Value="50" Text="50"></asp:ListItem>

Event Handler

An event handler is added to support the change of selection.

In this case the change of selection will get the entries from the database, using the new page size.

Protected Sub ddlPageSizeChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ddlPageSize.SelectedIndexChanged
    PageSize =ddlPageSize.SelectedValue
    PageIndex = 0
    BindData(Filter, ddlSearchType.SelectedValue, SortExpression, SortDirection)

  Catch exc As Exception 'Module failed to load
    ProcessModuleLoadException(Me, exc)
  End Try
End Sub

The BindData function handles the querying of the database, the assignment of the results to the GridView and the display and parameters of the paging control.

Linking to a Different Local Resource File

DotNetNuke allows the resource file to be defined as an alternative to taking the default file.

Creating a DNN module the resource files are a great way of making the text for field labels and content intros and instructions available.

With the use of a resource file I can create a form with default text and then discuss the final text with the client, readily changing the words, as all are brought together in the resource files.

To reference text from a resource file, perhaps for a drop down list:

lblIntro.Text = Services.Localization.Localization.GetString(“lblIntro”, Me.LocalResourceFile)

In this example the content of the label lblIntro is populated using the entry lblIntro found in the default associated resource file.

If the given file is form.ascx.vb then the associated resource file will be App_LocalResources/form.ascx.vb.resx

To bring these entries together within a specified file replace the second parameters me.local resource file with a reference to the required file

then the example is below

lblIntro.Text = Services.Localization.Localization.GetString(“intro”, Services.Localization.Localization.GetResourceFile(Me, “form-opt1.ascx.vb”))

I have used the option to configure my own resource file when the default file is not automatically configured and available. Also where I have more than one configured presentation for a form. I can duplicated the resource file , tailoring the form entries according to the presentation.

Adding Guidance Text to an ASP.NET Textbox

Pre-loading a textbox with content can be used to indicate the format of the text to be entered. Instructions within the textbox can create a cleaner website.

For a cleaner, minimalist website moving the instruction words within a text box reduces the clutter on a page.

where space on the web page is at a premium putting the text within the box can save on the surrounding space.

An example of this is a search box with a magnifying glass to click, and words such as Search within.

Adding text in a textbox can help to show the website visitor the type of entry which you are expecting. For example the date format or time format hh:mm.

The aim is to be able to have some initial text within a textbox to illustrate
its purpose. In this example a textbox shall be pre-populated with the time layout. It will also be given a silver colour to illustrate that its guidance text.

The ASP.NET textbox is defined as :

<asp:TextBox id=”tbxStartTime” ForeColor=”silver” Columns=”5″
runat=”server” >HH:MM</asp:TextBox>

When the user clicks within the textbox we want to remove our helpful text, and
reset the colour from silver. In our code behind we have:

tbxStartTime.Attributes.Add(“OnClick”, “this.value=”; ”;”)

Get Image Width and Height

For an image file VB.NET can obtain the width and height of the image using the System.Drawing width and height properties.

Let us assume that our file image is /images/kennet_avon_canal.jpg and that we are going to illustrate the information we have found by using a label control lblImageInfo.

It is easier to import the drawing namespace and to use the shortened forms for referencing the functions.

Imports System.Drawing

The control for the label lblImageInfo is defined as

Protected WithEvents lblImageInfo As System.Web.UI.WebControls.Label

We will also define the parameters which we will be using

Dim imgImage As Bitmap
Dim imgWidth As Integer
Dim imgHeight As Integer
Dim strImageURL as String

To begin assign the image URL to a variable strimageURL.

strImageURL = “/images/kennet_avon_canal.jpg”

And assign our discovered values, after creating imgImage as a new Bitmap.

imgImage = New Bitmap(Server.MapPath(strImageURL))
imgWidth = imgImage.Width
imgHeight = imgImage.Height

Finally we will set the discovered width and height parameters of the image, plus the image itself, as the text parameter of our label control.

lblImageInfo.Text = “<div><img height= src=””” & imgImage & “”” width=””” & imgWidth & “”” height= “”” & imgHeight&”””></div>”
lblImageInfo.Text += “<div>Width = ” & imgWidth& “></div>”
lblImageInfo.Text +=  “<div>Height = ” & imgHeight & “></div>”