CustomValidator with Client JavaScript

I had crafted a custom validator for an DNN asp.net web page with a function to validate form elements.

Using the DNN pop-up calendar, with appropriate date formatting according to the browser, had issues with visitors not setting the language within the browser correctly. It was also decided that using 3 dropdownlists would provide a better control of the selection, and less issue with date selection on mobile devices using the pop up calendar.

I added 3 drop down lists to a web page to facilitate date selection.

To ensure that the date was valid I created a custom control to be referenced on the page with validateDate()

Initially I found that the function was firing, but that the status wasn’t being returned.

The JavaScript function was amended, requiring both sender and args parameters, like so:

<script type="text/javascript">
function validateDate(sender,args) {
    var ddlDay = $("#<% = ddlTheDay.clientid %>");
    var ddlMonth = $("#<% = ddlTheMonth.clientid %>");
    var ddlYear = $("#<% = ddlTheYear.clientid %>");

    document.getElementById('<% = cvTheDay.clientid %>').style.display = 'none';
    document.getElementById('<% = cvTheMonth.clientid %>').style.display = 'none';
    document.getElementById('<% = cvTheYear.clientid %>').style.display = 'none';

    // check date was selected
    if (ddlDay.val() < 0 ||
        ddlMonth.val() < 0 ||
        ddlYear.val() < 0) { // if ($('.validateDate').hasClass('validDate')){ // $('.validateDate').toggleClass('inValidDate validDate'); //} args.IsValid = false; return false; } // ensure days value correct if (ddlDay.val() > daysInMonth(ddlMonth.val(), ddlYear.val())) {
        args.IsValid = false;
        return false;
    }


    // check date is valid
    var dobDate = new Date(ddlYear.val(), ddlMonth.val() - 1, ddlDay.val());

    if (Object.prototype.toString.call(dobDate) === "[object Date]") {
        if (isNaN(dobDate.getTime())) {
            // date is not valid
            args.IsValid = false;
            return false;
        }
        else {
            // date is valid
            args.IsValid = true;
            return true;
        }
    }
    else {
        // not a date
        args.IsValid = false;
        return false;
    }
}

function daysInMonth(month, year) {
    return new Date(year, month, 0).getDate();
}
</script>

Shown below are the dropdownlists, together with their custom validators.

<asp:dropdownlist id="ddlTheDay" visible="true" runat="server" name="ddlTheDay" class="ddlTheDay" />
<asp:dropdownlist id="ddlTheMonth" visible="true" runat="server" name="ddlTheMonth" class="ddlTheMonth" />
<asp:dropdownlist id="ddlTheYear" visible="true" runat="server" name="ddlTheYear" class="ddlTheYear" />
<asp:customvalidator id="cvTheDay" runat="server" SetFocusOnError="True"
Display="Dynamic" ErrorMessage="The date is invalid!" ControlToValidate="ddlTheDay" ClientValidationFunction="validateDate" />
<asp:customvalidator id="cvTheMonth" runat="server" SetFocusOnError="True"
Display="Dynamic" ErrorMessage="The date is invalid!" ControlToValidate="ddlTheMonth" ClientValidationFunction="validateDate" />
<asp:customvalidator id="cvTheYear" runat="server" SetFocusOnError="True"
Display="Dynamic" ErrorMessage="The date is invalid!" ControlToValidate="ddlTheYear" ClientValidationFunction="validateDate" />
<div class="validateDate validDate">The date is invalid!</div>

As can be seen above I am using just the one div with the error announcement. Its default setting is within the module’s CSS file module.css, details are below:

.validateDate{color:#d00;font-weight:bold;}
.validDate{display:none;}
.invalidDate{display:block;}

A RadioButtonList in a GridView

A GridView is to include a RadioButtonList in its presentation. The options are to be populated as fixed options, not taken from a database.

The example below takes values from the DotNetNuke Lists and displays them as a radio button list.

In the presentation file there is a GridView, called gdvMembership

<asp:GridView ID="gdvMembership" runat="server"
  AllowPaging="false"
  AllowSorting="false"
  AutoGenerateColumns="false"
  GridLines="none"
  cellspacing="1"
  border="0"
>
  <Columns>
    <asp:TemplateField ItemStyle-HorizontalAlign="left" ItemStyle-Width="80%">
    <ItemTemplate>
    <asp:RadioButton ID="rbnOptions" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.Text")  %>' GroupName='<%# DataBinder.Eval(Container, "DataItem.Value")  %>' Checked='<%# DataBinder.Eval(Container, "DataItem.Selected")  %>' AutoPostBack="true" OnCheckedChanged="setSelection" />
    </ItemTemplate>
    </asp:TemplateField>
  </Columns>
</asp:GridView>

In the code behind, a subroutine is used to populate the GridView and to set the selected item.

Private Sub Registration(ByVal SeclectedValue as string)
  Dim dt as DataTable = new DataTable
  dt.Columns.Add(New DataColumn("Text"))
  dt.Columns.Add(New DataColumn("Value"))
  dt.Columns.Add(New DataColumn("Enabled"))
  Dim row as dataRowrow = dt.newRow()
  row("Text") = "I am registered with the organisation"
  row("Value") = "Registered"
  row("Enabled") = True"
  If SelectedValue Is Nothing Then
    row("Selected") = False
  ElseIf SelectedValue = "Registered" Then
    row("Selected") = True
  Else
    row("Selected") = False
  End If
  dt.Rows.Add(row)row = dt.newRow()
  gdvMembership.DataSource = dt
  gdvMembership.DataBind()
End Sub

Whilst populating the rest of the page content the above sub-routine is called with the value of the registration status.

Registration(objIApplication.Membership)

Radio buttons of a different row in a GridView cannot be grouped together. The issue is caused by each row in the GridView being given a different ident.

The radiobuttons are therefore not of the same name once the page is rendered.

<input id=”dnn_ctr485_application_gdvMembership_rbnOptions_0″ name=”dnn_ctr485_application_gdvMembership_rbnOptions_1″…>

Use the GroupName parameter.

I had considered using JQuery to change uncheck the other options when the selection is changed. However, I chose to use an auto postback and a call to a function: don’t forget to add AutoPostBack=”true”.

Protected Sub setSelection(ByVal sender As Object, ByVal e As System.EventArgs)
  For Each row As GridViewRow In gdvMembership.Rows
    Dim rb As RadioButton = TryCast(row.FindControl("rbnCUOptions"), RadioButton)
    Dim rbn As RadioButton = TryCast(sender, RadioButton)
    If Not rb Is rbn Then
      rb.Checked = False
    End If
  Next
End Sub

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 , cmdAdd.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"
    AllowPaging="false"
    AllowSorting="false"
    AutoGenerateColumns="false"
    >
  <Columns>                            
    <asp:TemplateField ItemStyle-HorizontalAlign="left" ItemStyle-Width="80%">
      <ItemTemplate>
        <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" />
      </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField ItemStyle-HorizontalAlign="Left" ItemStyle-Width="20%">
      <ItemTemplate>
        <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>
      </ItemTemplate>
    </asp:TemplateField>    
  </Columns>
</asp:GridView>

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
  Try
      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 vb.net

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)
Else
  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 VB.net handles on click, the function is simply declared.

The LinkButton declaration is given below. Unlike vb.net 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) {
base.OnLoad(e)
try {
cmdAdd.click += 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

References

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"
AllowPaging="False"
AutoGenerateColumns="False"
runat="server"
OnUpdateCommand="OnUpdateCommand" 
OnEditCommand="OnEditCommand" 
OnCancelCommand="OnCancelCommand" 
OnDeleteCommand="OnDeleteCommand
">
<Columns>
...
...

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"
    OnUpdateCommand="OnUpdateCommand" 
    OnEditCommand="OnEditCommand" 
    OnCancelCommand="OnCancelCommand" 
    OnDeleteCommand="OnDeleteCommand">
    <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" />
    <Columns>
        <asp:TemplateColumn HeaderText="Name">
            <ItemTemplate>
                <asp:Label runat="server" Visible="true" Text='<%# DataBinder.Eval(Container, "DataItem.name") %>' ID="Name" />
                <asp:Label runat="server" Visible="false" Text='<%# DataBinder.Eval(Container, "DataItem.TeamId") %>' ID="TeamId" />
            </ItemTemplate>
            <EditItemTemplate>
                <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" />
            </EditItemTemplate>
        </asp:TemplateColumn>
        <asp:EditCommandColumn Visible="True" ButtonType="LinkButton" UpdateText="Update" CancelText="Cancel" EditText="Edit" />
        <asp:TemplateColumn>
            <ItemTemplate>
                <asp:LinkButton runat="server" ID="Delete" Text="Delete" CommandName="Delete" CausesValidation="false" Visible="true" />
            </ItemTemplate>
        </asp:TemplateColumn>
    </Columns>
</asp:datagrid>

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)
 Try
	grdTeam.EditItemIndex = e.Item.ItemIndex
BindData()
 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)
 Try
	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
	BindData()
 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)
 Try
	grdTeam.EditItemIndex = -1
	BindData()
 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)
 Try
	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
	   objCTeam.UpdateTeam(objITeam)
	End If
	grdTeam.EditItemIndex = -1
	BindData()
 Catch exc As Exception 'Module failed to load
	ProcessModuleLoadException(Me, exc)
 End Try
End Sub

Below I include

Private Sub BindData()
 Try
	Dim objITeam As New TeamInfo
	Dim objCTeam As New TeamController
	grdTeam.DataSource = objCTeam.GetTeamList(ModuleId, PortalId)
	grdTeam.DataBind()
	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"
AllowPaging="False"
AutoGenerateColumns="False"
runat="server"
">
<Columns>
<asp:TemplateColumn HeaderText="Status" HeaderStyle-CssClass="subhead">
<ItemTemplate>
<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, "DataItem.name") %> 'runat="server"></asp:Label>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:datagrid>

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
  Try
    If (e.Item.ItemType = ListItemType.Item) Or (e.Item.ItemType = ListItemType.AlternatingItem) Then
      e.Item.Attributes.Add("onmouseover","this.style.backgroundColor='lemonchiffon';this.style.cursor='hand'")
      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
  Catch
  End Try
End Sub

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

Plums
Apples

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>
</asp:DropDownList>

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
  Try
    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.