|
|
|
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
|
<%@ 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.
|
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.
|
<%@ 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>
|
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
|
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
|
|