Back to
swartzentruber.net
 

Code Examples in VB.NET (Framework 1.1)

Code Samples Home


cachemanager

createlinkspagewithxml

hideorshowaddnew

lookupusercontrolwithevents

lookupusercontrolwithevents2

looplistboxforselected

tourcalendarinternational

tourcalendarwithdetail

tourcalendarwithdetail2

tourcalendarwithdetail3

usercontrol_sessionview

usertablestoarraylist_via_sqldmo

Tour Calendar With Detail Section - Part 3 - Click to Show Details
Summary & Comments

Okay, this is the fun part.  I am going to give the user 2 ways to view more details about a particular show or show day.  Show details will be displayed in an IFRAME.  The user can see details on a single show or for all shows on a single day.

We are mainly going to be adding to the code from Part 2.  We will also create a very simple display page that will be used as the src for our IFRAME.

Here is a working sample

ASPX Code
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="ItinSample.aspx.vb" Inherits="swartzentrubernet.ItinSample" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
</HEAD>
<body MARGINWIDTH="0" MARGINHEIGHT="0">
<form id="Form1" method="post" runat="server">
<center>
<table BORDER="1" CELLPADDING="10">
<tr bgcolor="#99cc99" bordercolor="#cc6600">
<td>
<asp:Label ID="lblMsg" Runat="server" CssClass="Alert"></asp:Label>
<table border="0" cellpadding="4">
<tr valign="top">
<tr valign="top">
<td><asp:Calendar OnSelectionChanged="CheckDay" OnVisibleMonthChanged="ChangeMonth" OnDayRender="Calendar1_DayRender" DayStyle-Height="75" DayStyle-Width="75" DayStyle-verticalalign="Top" DayStyle-Font-Size="8" NextPrevFormat="FullMonth" SelectionMode="Day" TitleStyle-Font-Bold="True" TitleStyle-Font-Name="Verdana" TitleStyle-Font-Size="14" BackColor="white" BorderColor="#FF6633" BorderStyle="Dashed" CellPadding="2" CellSpacing="2" Runat="server" id="Calendar1" OtherMonthDayStyle-ForeColor="#C0C0C0" DayStyle-BorderStyle="Solid" DayStyle-BorderWidth="1" TodayDayStyle-ForeColor="Red" Height="600" Width="750"></asp:Calendar></td>
<td>
<iframe frameborder="yes" scrolling="yes" id="Detail" height="200" width="200" name="Detail" src="ItinDay.aspx" runat="server">
</iframe>
</td>
</tr>
</table>
</td>
</tr>
</table>
</center> </form>
</body>
</HTML>

We just added a couple things to the page from Part 2.  We add one event handler to the calendar.

  • OnSelectionChanged - This event is triggered when the user clicks the day number in the calendar. 

We also added an IFRAME.  It is very important that you include the following attributes:

  • id
  • runat="server"
  • src=something

Otherwise, our codebehind will fail to work.

VB.NET Codebehind Code
Option Strict On
Option Explicit On

Imports System
Imports System.Text
Imports System.Drawing
Imports System.Data
Imports System.Data.SqlClient
Imports System.Web.UI.WebControls
Imports System.Web.UI
Imports System.Web.Caching

Public Class ItinSample
    Inherits System.Web.UI.Page
    Protected WithEvents Calendar1 As System.Web.UI.WebControls.Calendar
    Private cnString As String = ConfigurationSettings.AppSettings("test")
    Private dtDates As DataTable
    Protected WithEvents lblMsg As System.Web.UI.WebControls.Label
    Private curMonth As DateTime
    Private noDatesForMonth As Boolean = False

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Put user code to initialize the page here

        If Not Page.IsPostBack Then
            curMonth = Convert.ToDateTime(DateTime.Today.Month.ToString & "/1/" & DateTime.Today.Year.ToString)
            Calendar1.VisibleDate = curMonth
            LoadCacheForMonth(curMonth)
        End If

    End Sub

    Protected Sub ChangeMonth(ByVal sender As Object, ByVal e As MonthChangedEventArgs)

        curMonth = e.NewDate.Date
        LoadCacheForMonth(curMonth)

    End Sub

    Private Sub LoadCacheForMonth(ByVal curMonth As DateTime)

        ' loads dataset for a particular month into cache

        Dim iMonth As Integer = curMonth.Month
        Dim iYear As Integer = curMonth.Year
        Dim cacheName As String = iMonth.ToString & iYear.ToString & "Dates"

        If Cache(cacheName) Is Nothing Then
            dtDates = DatesForMonth(curMonth)
            Cache.Insert(cacheName, dtDates, Nothing, Cache.NoAbsoluteExpiration, _
                        TimeSpan.FromHours(3))
        Else
            dtDates = CType(Cache(cacheName), DataTable)
        End If

    End Sub

    Private Function DatesForMonth(ByVal Month As DateTime) As DataTable

        Dim cn As SqlConnection = New SqlConnection(cnString)
        Dim cmd As SqlDataAdapter = New SqlDataAdapter("GetDatesForMonth", cn)
        cmd.SelectCommand.CommandType = CommandType.StoredProcedure
        Dim dt As New DataTable()

        Try
            AppendSQLParameter(cmd.SelectCommand, "@startDate", SqlDbType.DateTime, ParameterDirection.Input, 8, Month)
            cmd.Fill(dt)
            cmd.Dispose()
            cn.Close()
        Catch x As SqlException
            lblMsg.Text = x.Message
        Finally
            cn = Nothing
        End Try

        Return dt

    End Function


    Protected Sub Calendar1_DayRender(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DayRenderEventArgs) Handles Calendar1.DayRender

        If noDatesForMonth Then Exit Sub         ' may have clicked selected date again
        If curMonth.Year = 1 Then
            curMonth = Convert.ToDateTime(Calendar1.SelectedDate.Month.ToString & "/1/" & Calendar1.SelectedDate.Year.ToString)
        End If


        Dim matchRows() As DataRow
        Dim myMonth As Integer = curMonth.Month
        LoadCacheForMonth(curMonth)
        If ((dtDates Is Nothing) OrElse (dtDates.Rows.Count = 0)) Then
            ' we have no cached datatable or the datatable is empty
            ' no dates to render for this month, shortcircuit any further processing
            noDatesForMonth = True
            Exit Sub
        End If

        Dim curDay As Integer
        Dim dr As DataRow
        Dim dayText As StringBuilder = New StringBuilder()
        Dim eventDay As Boolean
        Dim c As TableCell = e.Cell

        If e.Day.Date.Month = myMonth Then
            curDay = e.Day.Date.Day
            matchRows = dtDates.Select("ShowDay=" & curDay.ToString)
            For Each dr In matchRows
                eventDay = True
                dayText.Append("<br><b>")
                dayText.Append(Convert.ToString(dr.Item("Venue")))
                dayText.Append("</b>")
            Next
            If eventDay Then
                e.Cell.BackColor = Color.Pink
                c.Controls.Add(New LiteralControl(dayText.ToString))
                dayText = New StringBuilder()
            End If
        End If

    End Sub
End Class


Option Strict On
Option Explicit On

Imports System
Imports System.Text
Imports System.Drawing
Imports System.Data
Imports System.Data.SqlClient
Imports System.Web.UI.WebControls
Imports System.Web.UI
Imports System.Web.Caching

Public Class ItinSample
    Inherits System.Web.UI.Page
    Protected WithEvents Calendar1 As System.Web.UI.WebControls.Calendar
    Private cnString As String = ConfigurationSettings.AppSettings("test")
    Private dtDates As DataTable
    Protected WithEvents lblMsg As System.Web.UI.WebControls.Label
    Private curMonth As DateTime
    Private noDatesForMonth As Boolean = False
    Protected detail As System.Web.UI.HtmlControls.HtmlGenericControl


    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Put user code to initialize the page here

        If Not Page.IsPostBack Then
            curMonth = Convert.ToDateTime(DateTime.Today.Month.ToString & "/1/" & DateTime.Today.Year.ToString)
            Calendar1.VisibleDate = curMonth
            LoadCacheForMonth(curMonth)
        End If

    End Sub

    Private Sub LoadCacheForMonth(ByVal curMonth As DateTime)

        ' loads dataset for a particular month into cache

        Dim iMonth As Integer = curMonth.Month
        Dim iYear As Integer = curMonth.Year
        Dim cacheName As String = iMonth.ToString & iYear.ToString & "Dates"

        If Cache(cacheName) Is Nothing Then
            dtDates = DatesForMonth(curMonth)
            Cache.Insert(cacheName, dtDates, Nothing, Cache.NoAbsoluteExpiration, _
                        TimeSpan.FromHours(3))
        Else
            dtDates = CType(Cache(cacheName), DataTable)
        End If

    End Sub

    Protected Sub ChangeMonth(ByVal sender As Object, ByVal e As MonthChangedEventArgs)

        Calendar1.SelectedDate = Nothing
       detail.Attributes("src") = "ItinDay.aspx"
        curMonth = e.NewDate.Date
        LoadCacheForMonth(curMonth)

    End Sub

    Private Function DatesForMonth(ByVal Month As DateTime) As DataTable

        Dim cn As SqlConnection = New SqlConnection(cnString)
        Dim cmd As SqlDataAdapter = New SqlDataAdapter("GetDatesForMonth", cn)
        cmd.SelectCommand.CommandType = CommandType.StoredProcedure
        Dim dt As New DataTable()

        Try
            AppendSQLParameter(cmd.SelectCommand, "@startDate", SqlDbType.DateTime, ParameterDirection.Input, 8, Month)
            cmd.Fill(dt)
            cmd.Dispose()
            cn.Close()
        Catch x As SqlException
            lblMsg.Text = x.Message
        Finally
            cn = Nothing
        End Try

        Return dt

    End Function

    Protected Sub CheckDay(ByVal sender As Object, ByVal e As EventArgs)

        Dim thisDay As String
        thisDay = Calendar1.SelectedDate.Month.ToString & "|" & _
            Calendar1.SelectedDate.Day.ToString & "|" & _
            Calendar1.SelectedDate.Year.ToString

        detail.Attributes("src") = "ItinDay.aspx?A=" & thisDay

        curMonth = Convert.ToDateTime(thisDay.Replace("|", "/"))

    End Sub

    Protected Sub Calendar1_DayRender(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DayRenderEventArgs) Handles Calendar1.DayRender

        If noDatesForMonth Then Exit Sub

        Dim matchRows() As DataRow
        Dim myMonth As Integer = curMonth.Month
        LoadCacheForMonth(curMonth)
        If ((dtDates Is Nothing) OrElse (dtDates.Rows.Count = 0)) Then
            ' we have no cached datatable or the datatable is empty
            ' no dates to render for this month, shortcircuit any further processing
            noDatesForMonth = True
            Exit Sub
        End If

        Dim curDay As Integer
        Dim dr As DataRow
        Dim dayText As StringBuilder = New StringBuilder()
        Dim eventDay As Boolean
        Dim c As TableCell = e.Cell

        If e.Day.Date.Month = myMonth Then
            curDay = e.Day.Date.Day
            matchRows = dtDates.Select("ShowDay=" & curDay.ToString)
            For Each dr In matchRows< BR >                 eventDay= True<BR>                dayText.Append("<br><b>")<BR>                dayText.Append(Convert.ToString(dr.Item("Venue")))<BR>                <STRONG>dayText.Append("</b><br>")<BR>                dayText.Append("<ahref='ItinDay.aspx?D=")
                dayText.Append(Convert.ToString(dr.Item("ItinID")))
                dayText.Append("' target='Detail'>View Detail</a>")
            Next
            If eventDay Then
                e.Cell.BackColor = Color.Pink
                c.Controls.Add(New LiteralControl(dayText.ToString))
                dayText = New StringBuilder()
            End If
        End If

    End Sub
End Class

The new stuff in the code behind is in bold.  Watch the wrapping.  We've added a reference to the IFRAME as an HtmlGenericControl.  This allows us to get to the src attribute and set it in the code behind.  I had to track down how to do this, so that's a freebie for you, thanks to the good people of the Microsoft newgroups.  Kinda cool actually.

In the ChangeMonth sub, I'm basically just resetting some values there when the month changes.

In the Calendar1_DayRender sub, I have added the hyperlink that will load the show details into the IFRAME.  Pretty basic.

The main new thing is the CheckDay sub, which handles the SelectionChanged event.  This is triggered when the user clicks the day number in the calendar, as I mentioned before.  I'm just grabbing the date and passing it to my details page.  The only reason I use the pipe ( | ) is because I didn't want slashes in my querystring.  Also, you have to set the curMonth variable again or your datatable won't have a valid reference.  Another one of those gotchas.

The only thing left to show you is the details page.  It's very simple and you can probably figure it out yourself, but for completeness.

ASPX Code for the detail page
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="ItinDay.aspx.vb" Inherits="swartzentrubernet.ItinDay" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
</HEAD>
<body bgcolor="#b0c4de">
<form id="Form1" method="post" runat="server">
<center>
<asp:Repeater ID="rptDetail" Runat="server">
<HeaderTemplate>
<table width="100%">
<tr>
<td bgcolor="#336699"><p class="HeaderGreen">Show Details</p>
</td>
</tr>
</table>
</HeaderTemplate>
<ItemTemplate>
<table bgcolor="#99cc99" width="100%">
<tr valign="top">
<td><p class="smblu">Date</p>
</td>
<td bgcolor="#FFFFFFF"><%# Databinder.Eval(Container.DataItem, "StartDate", "{0:d}") %></td>
</tr>
<tr valign="top">
<td><p class="smblu">Time</p>
</td>
<td bgcolor="#FFFFFFF"><%# Databinder.Eval(Container.DataItem, "StartTime", "{0:t}") %></td>
</tr>
<tr valign="top">
<td><p class="smblu">Venue</p>
</td>
<td bgcolor="#FFFFFFF"><%# Container.DataItem("Venue") %></td>
</tr>
<tr valign="top">
<td><p class="smblu">Location</p>
</td>
<td bgcolor="#FFFFFFF"><%# Container.DataItem("City") %>
<%# Container.DataItem("State") %>
<%# Container.DataItem("Country") %>
</td>
</tr>
</table>
</ItemTemplate>
<SeparatorTemplate>
<hr color="#336699" size="2">
</SeparatorTemplate>
</asp:Repeater></center>
</form>
</body>
</HTML>
VB.NET Codebehind Code for the detail page
Option Strict On
Option Explicit On

Imports System
Imports System.Text
Imports System.Data
Imports System.Data.SqlClient
Imports System.Web.UI.WebControls
Imports System.Web.UI

Public Class ItinDay
    Inherits System.Web.UI.Page
    Protected WithEvents rptDetail As System.Web.UI.WebControls.Repeater
    Private cnString As String = ConfigurationSettings.AppSettings("test")


    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Put user code to initialize the page here

        Try
            ' do generic error trap to throw away bad data
            Dim itinID As Integer = Convert.ToInt32(Request.QueryString("D"))
            Dim showDay As String = Convert.ToString(Request.QueryString("A"))
            Dim thisDay As DateTime

            If itinID > 0 Then
                RenderDetail(itinID)
            ElseIf showDay <> "" Then
                showDay = showDay.Replace("|", "/")
                thisDay = DateTime.Parse(showDay)
                RenderDay(thisDay)
            End If
        Catch x As InvalidCastException
            Response.Write("Invalid input")
        End Try
    End Sub

    Private Sub RenderDetail(ByVal ItinID As Integer)

        Dim detail As New StringBuilder()

        Dim cn As SqlConnection = New SqlConnection(cnString)
        Dim cmd As SqlCommand = New SqlCommand("GetDateDetail " & ItinID, cn)
        Dim myData As SqlDataReader

        Try
            cmd.Connection.Open()
            myData = cmd.ExecuteReader(CommandBehavior.CloseConnection)
        Catch e As SqlException
            myData = Nothing
        End Try

        rptDetail.DataSource = myData
        rptDetail.DataBind()

    End Sub

    Private Sub RenderDay(ByVal thisDay As DateTime)

        Dim detail As New StringBuilder()
        Dim cn As SqlConnection = New SqlConnection(cnString)
        Dim cmd As SqlCommand = New SqlCommand("GetAllDateDetail '" & thisDay & "'", cn)
        Dim myData As SqlDataReader

        Try
            cmd.Connection.Open()
            myData = cmd.ExecuteReader(CommandBehavior.CloseConnection)
        Catch e As SqlException
            myData = Nothing
        End Try

        rptDetail.DataSource = myData
        rptDetail.DataBind()

    End Sub 

End Class
AppendSqlParameter (part of my data access class called DataHelper)
Public Sub AppendSQLParameter(ByRef cmd As SqlCommand, _
                ByVal strParamName As String, _
                ByVal strDataType As SqlDbType, _
                ByVal strDirection As ParameterDirection, _
                ByVal lngSize As Integer, _
                ByVal varValue As Object)

        Dim param As SqlParameter

        If lngSize > 0 Then
            param = New SqlParameter(strParamName, strDataType, lngSize)
        Else
            param = New SqlParameter(strParamName, strDataType)
        End If
        param.Direction = strDirection
        If Not strDirection = ParameterDirection.Output Then
            If Not ((varValue Is System.DBNull.Value) Or (varValue Is Nothing)) Then
                param.Value = varValue
            Else
                param.Value = System.DBNull.Value
            End If
        End If

        cmd.Parameters.Add(param)

    End Sub

Anyway, that's a lot of code, but hopefully you can get something out of it. It ended up being more difficult than I anticipated, so maybe I can save you a few steps.  Thanks for reading.

Tour Calendar With Detail Part 1

Tour Calendar With Detail Part 2

© 1999-2008 swartzentruber.net