|
 |
aspx_beginners thread: Why won't DataList display when page renders?
Message #1 by "Jon Maz" <jonmaz@s...> on Sat, 18 May 2002 01:06:43
|
|
Hi All,
I have a problem that probably takes longer to explain than to solve, so I
hope someone has the patience to read the whole posting! I have included
all the relevant code below, and simplified it down as much as I can.
THE DESIGN AND THE PROBLEM
Basically I have a DataList bound to a DataTable. When the page
PreRenders, new rows are added to the DataTable, and the DataList is
rebound to it, so the DataList SHOULD display the new data automatically
on Page_PreRender. This is what I want.
But in fact these new rows are not displayed until a button is pressed (I
DON'T want to have to wait for the button click). The strange thing is
that pressing the button calls exactly the same routine that
Page_PreRender calls, so I have no idea why clicking the button causes the
subroutine to work, while the same subroutine called from Page_PreRender
apparently doesn't work!
In the actual code the DataList is inside a UserControl, which is within
another UserControl, which is inside a DataGrid (!), but the basic
principle - and basic problem - is as described above. Now I'll try to
explain how the page is structured, so no one has to spend too much time
working out my code.
THE CODE EXPLAINED
There is a main aspx page ("MainPage.aspx") which holds a UserControl
("MainUserControl.ascx") inside a DataGrid. Within this
MainUserControl.ascx there are two further UserControls, one on the left
hand side of a table ("SubUserControl_LHS.ascx") and one on the right
("SubUserControl_RHS.ascx"). The left hand UserControl has a DropDownList
and a LinkButton, the right hand UserControl has a DataList within it.
The page is part of a forum site, and its purpose is to display and allow
editing of a list of Author(s) of a given message (messages to this forum
CAN have multiple authors). The page will first pull the author(s) of a
particular message out of an Access database, and display these names in
the DataList in SubUserControl_RHS.ascx.
The page user will then be able to edit this "Authors" list in two ways:
1) by clicking on a displayed name, that name is REMOVED from the
list of authors (this is handled by Sub myDataList_DeleteCommand within
SubUserControl_RHS.ascx)
2) the user can ADD to the list of Authors by selecting from the
DropDownList and clicking the LinkButton in SubUserControl_LHS.ascx.
However (1) and (2) these parts of the page work fine - I have just
included them to help understand the code. It is the initial display of
author(s) pulled from the Database which is NOT working.
To simplify things, I have replaced the Access query with a simple fixed
ArrayList in MainPage.aspx:
myAL.Add("Bob")
myAL.Add("Jimmy")
myAL.Add("Eric")
but this simplified code still displays the same problem. So imagine
that "Bob", "Jimmy" and "Eric" are the three authors of the current
message that have been pulled from the database.
The Public Sub "AddPerson" in SubUserControl_RHS.ascx controls the adding
of these authors to the DataTable, and then DataBinding this DataTable to
the DataList. When called, this subroutine checks that the passed name is
not already in a DataTable (which itself is stored in the ViewState), and
if the name is not a duplicate, it adds a new row to a DataTable and then
DataBinds the DataTable.
So, when MainPage.aspx first loads, what SHOULD happen is this:
a) MainPage.aspx's PreRender finds the MainUserControl in the DataGrid
and passes the Bob/Jimmy/Eric ArrayList to the DisplayNames subroutine in
MainUserControl.ascx
b) DisplayNames loops through this little ArrayList, each time passing a
name to the AddPerson subroutine of SubUserControl_RHS.ascx
c) AddTable pulls a pre-built DataTable out of the ViewState, checks that
the name it has received is not a duplicate name, adds the name to a new
row of the DataTable, puts the amended DataTable back into the ViewState,
and binds the DataList to the amended DataTable.
d) The DataList displays the added name(s)
**************** THE PROBLEM *********************
This last step (d) IS WHERE THE PROBLEM IS - the names are NOT displayed
on Page_PreRender.
In fact, the DataList displays absolutely nothing on Page_PreRender. But
then - oddly - if I select a name from the DropDownList in
SubUserControl_LHS.ascx, and click the "Add User" button, the names Bob,
Jimmy and Eric pop out of the ether and show up in the DataList, along
with the name just selected from the DropDownList!
So it seems most of the code HAS worked! The names Bob, Jimmy and Eric
seem to be in the DataTable, but for some reason are NOT being displayed
in the DataList on Page_PreRender, but only when the LinkButton is clicked
(which is too late)
Congratulations for reading this far! Now you understand the problem, I
hope you can tell me what's going on and how to fix it!
Thanks in advance,
Cheers,
JON
++++++++++++++++++++++++++
MainPage.aspx
++++++++++++++++++++++++++
<%@ Page Language="VB" Trace="true" Debug="true" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.Oledb" %>
<%@ Register TagPrefix="UserControl" TagName="Article"
src="MainUserControl.ascx" %>
<script language="VB" runat="server">
Dim myAL As New ArrayList()
Sub Page_Load(sender as object, e as eventargs)
'*** dummy HashTable just to give the dg a shape!
Dim myHT As New Hashtable()
myHT.Add("ABC", "XYZ")
dg.DataSource = myHT
'*******************************************
'*** HERE IS THE PROBLEM
'*** These names should appear automatically
'*** in the DataList in SubUserControl_RHS.ascx
'*** when this MainPage.aspx PreRenders
'*** BUT THEY DON'T!
'*******************************************
myAL.Add("Bob")
myAL.Add("Jimmy")
myAL.Add("Eric")
If Not Page.IsPostBack Then
dg.EditItemIndex = 0 '*** DataGrid opens in Edit Mode
dg.Databind()
End If
End Sub
Sub Page_PreRender(sender As Object, e As EventArgs)
'*** The UserControl is not found if I do this in Page_Load
Dim item as DataGridItem
For Each item In dg.Items
If (Item.ItemType = ListItemType.EditItem) then
If Not Page.IsPostBack then
Dim ucArticle as AddArticleTemplate = Item.FindControl
("ucArticle")
'*** THE DISPLAYNAMES SUB IS CALLED HERE ****
ucArticle.DisplayNames(myAL)
end if
end if
Next item
end sub
</script>
<html>
<form runat="server">
<asp:DataGrid id="dg" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:TemplateColumn>
<EditItemTemplate>
<UserControl:Article id="ucArticle" runat="server" />
</EditItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:dataGrid>
</form>
</body>
</html>
++++++++++++++++++++++++++
MainUserControl.ascx
++++++++++++++++++++++++++
<%@ Control Language="VB" ClassName="AddArticleTemplate" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.Oledb" %>
<%@ Register TagPrefix="LHS" TagName="UserControl"
src="SubUserControl_LHS.ascxx" %>
<%@ Register TagPrefix="RHS" TagName="UserControl"
src="SubUserControl_RHS.ascx" %>
<script language="VB" runat="server">
Sub Page_Load(obj as object, e as EventArgs)
If not Page.IsPostBack
DataBind()
end if
end sub
Protected Overrides Function OnBubbleEvent(obj As Object, e As EventArgs)
As Boolean
'*** to detect bubble event in SubUserControl_LHS.ascx
'*** and add selected person to DataTable in
SubUserControl_RHS.ascx
if obj.Text = "Add Author" then
RHSUserControl.AddPerson
(LHSUserControl.SelectedPersonName, LHSUserControl.SelectedPersonValue)
end if
Return True
End Function
'*** THIS ROUTINE SHOULD DISPLAY THE NAMES ***
Public Sub DisplayNames(objExistingMessageDetails as ArrayList)
Dim TempAL as ArrayList = objExistingMessageDetails
Dim myEnumerator As System.Collections.IEnumerator =
TempAL.GetEnumerator()
While myEnumerator.MoveNext()
RHSUserControl.AddPerson(myEnumerator.Current, 1)
End While
End Sub
</script>
<asp:Table runat="server">
<asp:TableRow>
<asp:TableCell VerticalAlign="top" width="50%">
<LHS:UserControl runat="server" id="LHSUserControl" />
</asp:TableCell><asp:TableCell width="50%">
<RHS:UserControl runat="server" id="RHSUserControl" />
</asp:TableCell>
</asp:TableRow>
</asp:Table>
++++++++++++++++++++++++++
SubUserControl_RHS.ascx
++++++++++++++++++++++++++
<%@ Control Language="VB" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.Oledb" %>
<script language="VB" runat="server">
Dim objDatabase as new BusinessObjects.Database
Dim ds as new DataSet()
Dim myDataTable as DataTable
Dim myColumn as DataColumn
Dim myRow as DataRow
Sub Page_Load(obj as object, e as eventargs)
objDatabase.ConnectionString = ConfigurationSettings.AppSettings
("ConnectionString")
objDatabase.DataSet = ds
If Not IsNothing(ViewState("PeopleToAdd")) then
myDataList.DataSource = ViewState("PeopleToAdd")
end if
If not Page.IsPostBack
DataBind()
'*** Set up the DataTable in ViewState ***
myDataTable = new DataTable("PeopleToAdd")
myColumn = myDataTable.Columns.Add("PersonID", System.Type.GetType
("System.Int32"))
myColumn.AllowDBNull = false
myColumn = myDataTable.Columns.Add("Name", System.Type.GetType
("System.String"))
myColumn.AllowDBNull = false
ViewState("PeopleToAdd") = myDataTable
end if
end sub
'*** THE DATALIST IS ADDED TO HERE **************
Public Sub AddPerson(SelectedPersonName as String, SelectedPersonValue as
Integer)
'*** adds to the DataTable "PeopleToAdd" in memory, holding the author(s)
of the Item
'*** Pull the DataTable out of the ViewState
myDataTable = ViewState("PeopleToAdd")
'*** Check you aren't entering the same person twice
If objDatabase.CheckForDuplicateValuesInDataTable(myDataTable, "Name",
SelectedPersonName) = true then
lbDuplicate.Text = "Duplicate Value found! - no item added!"
Else
'*** Add the row to the DataTable
myRow = myDataTable.NewRow()
myRow("PersonID") = SelectedPersonValue
myRow("Name") = SelectedPersonName
myDataTable.Rows.Add(myRow)
'*** Put everything back in the ViewState
ViewState("PeopleToAdd") = myDataTable
'*** Blank out any "duplicate found" error messages
lbDuplicate.Text = ""
myDataList.DataBind()
End if
End sub
Sub myDataList_DeleteCommand(obj as object, e as DataListCommandEventArgs)
myDataTable = ViewState("PeopleToAdd")
myDataTable.Rows.RemoveAt(e.Item.ItemIndex)
ViewState("PeopleToAdd") = myDataTable
myDataList.DataBind()
lbDuplicate.Text = "" '*** Blank out any "duplicate found" error
messages
End sub
Public ReadOnly Property Authors As ArrayList
Get
myDataTable = ViewState("PeopleToAdd")
dim tempArrayList as New ArrayList()
dim tempRow as DataRow
for each tempRow in myDataTable.Rows
tempArrayList.Add(tempRow("PersonID"))
next tempRow
Return tempArrayList
End Get
End Property
</script>
<b>Authors (click to delete):</b>
<asp:DataList runat="server"
id="myDataList"
repeatlayout = "flow"
repeatdirection = "horizontal"
OnDeleteCommand = "myDataList_DeleteCommand">
<ItemTemplate>
<asp:LinkButton runat="server" Text='<%# Container.DataItem
("Name") %>' CommandName="Delete" /> ///
</ItemTemplate>
</asp:DataList>
<asp:Label runat="server" id="lbDuplicate" />
++++++++++++++++++++++++++
SubUserControl_LHS.ascx
++++++++++++++++++++++++++
<%@ Control Language="VB" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.Oledb" %>
<script language="VB" runat="server">
Dim objDatabase as new BusinessObjects.Database
Dim ds as new DataSet()
Dim myDataTable as DataTable
Dim myColumn as DataColumn
Dim myRow as DataRow
Sub Page_Load(obj as object, e as eventargs)
objDatabase.ConnectionString = ConfigurationSettings.AppSettings
("ConnectionString")
objDatabase.DataSet = ds
ddDDL.DataSource = objDatabase.CreateDataTableDefaultView
("tblPostedBy", "SELECT tblPeople.PersonID, tblPeople.FullName FROM
tblPeople;")
ddDDL.DataTextField = "People"
ddDDL.DataValueField = "PersonID"
If not Page.IsPostBack
DataBind()
end if
end sub
Public ReadOnly Property SelectedPersonName As String
Get
Return ddDDL.SelectedItem.Text
End Get
End Property
Public ReadOnly Property SelectedPersonValue As Integer
Get
Return ddDDL.SelectedItem.Value
End Get
End Property
</script>
Authors - choose from list:
<asp:DropDownList id="ddDDL" runat="server" />
<asp:LinkButton runat="server" Text="Add Author" id="lbLinkButton" />
Message #2 by "Jon Maz" <jonmaz@s...> on Wed, 22 May 2002 17:13:48
|
|
Hi All,
I solved the problem eventually. In SubUserControl_RHS.ascx, I had to
move the line:
myDataList.DataSource = ViewState("PeopleToAdd")
into the Page_Load If Not Page.IsPostBack subroutine, giving this:
If not Page.IsPostBack
myDataTable = new DataTable("PeopleToAdd")
myColumn = myDataTable.Columns.Add("PersonID", System.Type.GetType
("System.Int32"))
myColumn.AllowDBNull = false
myColumn = myDataTable.Columns.Add("Name", System.Type.GetType
("System.String"))
myColumn.AllowDBNull = false
ViewState("PeopleToAdd") = myDataTable
'**** PUT THE LINE HERE INSTEAD!
myDataList.DataSource = ViewState("PeopleToAdd")
DataBind()
end if
Cheers,
JON
|
|
 |