Designing the Browsing Interface

The next step in building dotBoard is to determine how to browse through the Boards,Threads, and Posts.When a user first enters the site and views the default page, they should be shown a list of Boards and descriptions they can choose to view.This code is located in default.aspx and default.aspx.vb.

Board Browsing

Browsing through our boards isn't very difficult. All we need to do is use a Repeater control, and create a custom DataSet out of our list of Board objects. Unfortunately, the only control we can drag and drop onto a Web Form is a Repeater control, and you can't drag controls into the Repeater, so we are going to have to look at the actual quasi-HTML that ASP.NET uses and write the repeated content by hand, as shown in Figure 13.50.

Figure 13.50 The Repeater Control (Default.aspx)

<asp:Panel runat="server">

<asp:Repeater id="Repeater1" runat="server"> <HeaderTemplate>

Figure 13.50 Continued

<div class="header">Available boards</div> </HeaderTemplate> <SeparatorTemplate>

<br><br> </SeparatorTemplate> <ItemTemplate>

<a href='board.aspx?boardid=

<%#DataBinder.Eval(Container, "DataItem.BoardName")%>'> <%#DataBinder.Eval(Container, "DataItem.BoardName")%>

<%#DataBinder.Eval(Container, "DataItem.BoardDescription")%> </ItemTemplate> </asp:Repeater> </asp:Panel>

The repeater code creates a header template, separator template, and the actual item template. The only thing we haven't discussed thus far is what data source the Repeater should use. Since the Repeater control requires a real data source (i.e., DataSet or something similar), what needs to be done is our list of Boards needs to be "translated" into a DataSet.Take a look at the updated code-behind for the default page in Figure 13.51.

Figure 13.51 The Updated Code-Behind (Default.aspx.vb)

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 Me.ApplyStyles(Me.Controls) Me.DisplayBoards() End Sub

Private Sub DisplayBoards()

Dim myBoards As DataSet = New DataSet() Dim list As ArrayList

Continued

Figure 13.51 Continued list = dotBoardObjects.MessageBoard.GetBoards() myBoards.Tables.Add("boards")

Dim myTable As DataTable = myBoards.Tables(0) myTable.Columns.Add("BoardName", GetType(String)) myTable.Columns.Add("BoardDescription", GetType(String))

Dim i As Integer

Dim myBoard As dotBoardObjects.Board myBoard = CType(list(i), dotBoardObjects.Board)

Dim fields(1) As Object fields(0) = myBoard.Name fields(1) = myBoard.Description myTable.Rows.Add(fields) myTable.AcceptChanges() Next i myBoards.AcceptChanges()

Repeater1.DataMember = "boards" Repeater1.DataSource = myBoards Repeater1.DataBind() End Sub

Notice the addition to the Page_Load method in this file. This subroutine now calls the DisplayBoards subroutine. DisplayBoards restructures the list of Boards into an appropriate form for a Repeater control to use. First, it creates a DataSet and gets the list of Boards from the MessageBoard class. Next, it creates a new table in the DataSet and adds three columns to it. Next, it loops through the list of Boards and builds an object array of the fields to add to the DataSet. It then adds a new row by passing in the object array to the Add method of the

Rows collection. Finally, it accepts the changes, and forces the Repeater control to DataBind to the DataSet. Look at Figure 13.52 to see what this page looks like.

Figure 13.52 The Default Page with Boards Displayed

Figure 13.52 The Default Page with Boards Displayed

Thread Browsing

Once the user has clicked one of the board links from default.aspx, they are taken to board.aspx.This page will be responsible for determining which board was selected and for displaying the appropriate threads. Displaying the Threads in a Board will function nearly identically to how displaying Boards functioned. Let's take a look at the important quasi-HTML that this page uses in Figure 13.53.

Figure 13.53 The ASPX Code for Board.aspx

<table cellpadding="0" cellspacing="0" border="0"> <asp:Repeater runat="server" id="Repeater1"> <SeparatorTemplate>

<tr> <td colspan="2"> &nbsp; </td> </tr> </SeparatorTemplate> <ItemTemplate> <tr>

Continued

Figure 13.53 Continued started by

<%#DataBinder.Eval(Container, "DataItem.creatorName")%> </td> <td>

<%#DataBinder.Eval(Container, "DataItem.postCount")%> total posts </td> </tr> <tr>

<td colspan="2"> <a href='thread.aspx?

<%#DataBinder.Eval(Container, "DataItem.threadLink")%>

<%#DataBinder.Eval(Container, "DataItem.threadSubject")%> </a> </td> </tr> </ItemTemplate> </asp:Repeater> </table>

The repeater code creates a separator template and the actual item template. It DataBinds the appropriate fields in the data source to items in the template. Let's take a look at how we get the data into the data source in Figure 13.54.

Figure 13.54 Board.aspx.vb

Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Dim mBoard As dotBoardObjects.board Dim boardId As String boardId = Request.QueryString.Item("boardid") Dim myLabel As Label myLabel = CType(Me.FindControl("lblHeader"), Label)

Figure 13.54 Continued myLabel.Text = boardId mBoard = New dotBoardObjects.board(boardId)

Dim myThreads As DataSet myThreads = New DataSet() myThreads.Tables.Add("threads")

Dim myTable As DataTable myTable = myThreads.Tables(O)

myTable.Columns.Add("threadLink", GetType(String)) myTable.Columns.Add("threadSubject", GetType(String)) myTable.Columns.Add("postCount", GetType(Integer)) myTable.Columns.Add("creatorName", GetType(String))

Dim i As Integer

For i = 0 To mBoard.ChildThreads.Count - 1 Dim myThread As dotBoardObjects.Thread myThread = mBoard.ChildThreads.Item(i)

Dim fields(3) As Object fields(0) = "BoardId=" & boardId & _

"&ThreadId=" & myThread.ID.ToString() fields(1) = myThread.Subject fields(2) = myThread.ChildPosts.Count fields(3) = myThread.Creator.Username myTable.Rows.Add(fields) myTable.AcceptChanges() Next i myThreads.AcceptChanges()

Continued

Figure 13.54 Continued

Repeater1.DataMember = "threads" Repeater1.DataSource = myThreads Repeater1.DataBind()

Me.ApplyStyles(Me.Controls) End Sub

Just like default.aspx, the data binding is relatively straightforward. First, we need to get a reference to the current Board.We do this by requesting the board name from the query string and initializing the board using it. Next, we set a label's text property to the name of the board, so the user knows what board he's in. Then we create a DataSet, add a table to it, and add all the required columns. Afterward, we iterate through the Board's child threads and create an object array to hold the necessary fields to add to the DataSet. Finally, we add all the rows to the DataSet and force the Repeater control to DataBind.Take a look at Figure 13.55 to see what the completed page looks like.

Figure 13.55 The Board Page with Threads Displayed

Figure 13.55 The Board Page with Threads Displayed

Message Browsing

The last piece to browsing the message board is to see individual Posts themselves. Just like Boards and Threads, displaying this data is accomplished by using a Repeater control and a DataSet. Let's take a look at the important quasi-HTML and the code-behind in Figures 13.56 and 13.57.

Figure 13.56 Thread.aspx

<asp:Repeater runat="server" id="Repeater1"> <ItemTemplate> <tr>

<td>posted by

<%#DataBinder.Eval(Container, "DataItem.postCreatorName")%> <%#DataBinder.Eval(Container, "DataItem.postCreatorEmail")%> </td> <td>

posted at

<%#DataBinder.Eval(Container, "DataItem.postDate")%> </td> </tr> <tr>

<%#DataBinder.Eval(Container, "DataItem.postSubject")%>

<%#DataBinder.Eval(Container, "DataItem.postBody")%> </td> </tr> </ItemTemplate> </asp:Repeater>

Figure 13.57 Thread.aspx.vb

Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Dim boardId As String Dim threadId As Long boardId = Request.QueryString.Item("boardId") threadId = CLng(Request.QueryString.Item("threadId"))

Dim myBoard As dotBoardObjects.board myBoard = New dotBoardObjects.board(boardId)

Dim myThread As dotBoardObjects.thread myThread = myBoard.ChildThread(threadId)

lblHeaderBoard.Text = myBoard.Name lblHeaderThread.Text = myThread.Subject

Dim myPosts As DataSet myPosts = New DataSet() myPosts.Tables.Add("posts")

Dim myTable As DataTable myTable = myPosts.Tables(0)

myTable.Columns.Add("postId", GetType(Long)) myTable.Columns.Add("postSubject", GetType(String)) myTable.Columns.Add("postBody", GetType(String)) myTable.Columns.Add("postDate", GetType(Date)) myTable.Columns.Add("postCreatorName", GetType(String)) myTable.Columns.Add("postCreatorEmail", GetType(String))

Dim i As Integer

For i = 0 To myThread.ChildPosts.Count - 1

Figure 13.57 Continued

Dim myPost As dotBoardObjects.Post myPost = myThread.ChildPosts.Item(i)

Dim fields(5) As Object fields(0) = myPost.ID fields(l) = myPost.Subject fields(2) = myPost.Body fields(3) = myPost.PostDate fields(4) = myPost.Creator.Username If Me.IsLoggedIn = True Then fields(5) = "<a href='mailto:" & myPost.Creator.Email & _ "'>email</a>"

Else fields(5) = "" End If myTable.Rows.Add(fields) myTable.AcceptChanges() Next i myPosts.AcceptChanges()

Repeaterl.DataMember = "posts" Repeaterl.DataSource = myPosts Repeater1.DataBind()

Me.ApplyStyles(Me.Controls) End Sub

Again, this code is nearly identical to that of the last two pages we've dealt with.The only real difference is that one of the fields is actually building a short HTML string. This is because the repeater can't handle if statements. So, in order to hide or show users' e-mail addresses depending on whether the viewer is logged in or not, we need to build a string instead of directly inserting the value. If the user is logged in, then the anchor tag for the poster's e-mail address is built; otherwise, an empty string is used.

0 0

Post a comment