Problems reading controls' properties when contained in a TemplatedColumn

S

starwiz

I'm trying to use the DataGrid's editing with a DropDownList. I've
tried using every code sample I've seen and none of them seem to be
able to solve my problem.

When I call e.Item.FindControl("name-of-my-DropDownList"), where e is a
DataGridCommandEventArgs passed to the UpdateCommand of the DataGrid, I
get an empty DropDownList. In fact, when I call
e.Item.FindControl("name-of-a-label") in the non-editable portion of my
template, I get an empty label.

ASP.Net doesn't have a problem with my accessing the DropDownList from
methods that it calls, interestingly enough. I can see the contents of
the DropDownList just fine when it calls its PreRender method and I
access the method's sender.

This is really weird...can someone lend me a hand here?

I'd really appreciate it.

-Starwiz

Here's my datagrid code (with appologies in advance to anyone whose
newsreader doesn't format this nicely):

<asp:datagrid id="DataGrid" datakeyfield="ID" (and other parameters)>
<columns>
<asp:templatecolumn headertext="Status">
<itemtemplate>
<asp:label id="lblStatus" enableviewstate="True"
runat="server" text='<%#
((System.Data.DataRowView)Container.DataItem)[StatusField] %>'>
</asp:label>
</itemtemplate>
<edititemtemplate>
<asp:dropdownlist autopostback="False"
enableviewstate="True" runat="server" id="ddlStatus"
onprerender="SetStatusIndex" />
</edititemtemplate>
</asp:templatecolumn>
<asp:editcommandcolumn buttontype="LinkButton"
updatetext="Update" canceltext="Cancel"
edittext="Edit"></asp:editcommandcolumn>
<!--The rest of the columns are auto-populated-->
</columns>
</asp:datagrid>
*********************
And my C# code:

private bool bindDataGrid = false;
private void ViewAll_PreRender(object sender, System.EventArgs e)
{
if(bindDataGrid)
RefreshDataGrid();
}

private void RefreshDataGrid()
{
//...this code doesn't matter much
//but let me know if you want to see it.
}

protected string SelectedStatus = null;
private void DataGrid_EditCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
SelectedStatus = ((Label)e.Item.FindControl("lblStatus")).Text;
//SelectedStatus is always an empty string.

DataGrid.EditItemIndex = e.Item.ItemIndex;
bindDataGrid = true;
}

protected void SetStatusIndex(object sender, EventArgs e)
{
DropDownList ddl = (DropDownList)sender;
DataTable dt = DBAccessor.GetPatientStatuses();
foreach(DataRow dr in dt.Rows)
ddl.Items.Add(new ListItem((string)dr["Status"],
((int)dr["StatusID"]).ToString()));

ddl.SelectedIndex =
ddl.Items.IndexOf(ddl.Items.FindByValue(SelectedStatus));
}

private void DataGrid_UpdateCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
int index = e.Item.DataSetIndex;
DataTable dt = (DataTable)Session[PatientDT];
int id = (int)dt.Rows[index][IDField];
DropDownList ddl = (DropDownList)e.Item.FindControl("ddlStatus");

int newStatus = int.Parse(ddl.SelectedValue);
//ddl.SelectedValue is always an empty string.
//In fact, ddl.Items is empty, too;
//there aren't any meaningful properties
//of the ddl that I can read at all.

DBAccessor.SetPatientStatus(id, newStatus);
DataGrid.EditItemIndex = -1;
bindDataGrid = true;
}

//Yes, this is messy. It was a failed attempt
//at fixing this problem that I just haven't gotten
//rid of yet...
private void DataGrid_ItemDataBound(object sender,
System.Web.UI.WebControls.DataGridItemEventArgs e)
{
if(e.Item.ItemType == ListItemType.EditItem)
{
DropDownList ddl = (DropDownList)e.Item.FindControl("ddlStatus");
if(ddl != null)
SetStatusIndex(ddl, null);
}
else if(e.Item.ItemType == ListItemType.Item)
{
try
{
Label lbl = (Label)e.Item.FindControl("lblStatus");
lbl.Text =
(string)((System.Data.DataRowView)e.Item.DataItem)[StatusField];
}
finally {}
}
}
 
G

Guest

I'm guessing that you're using a datasource to fill the dropdownlist, that
you're binding the datasource to the ddl *each* time the page loads, but only
filling the datasource *once* when the page first loads. Is that possible?

The reason you'll see things in Prerender and then not again is that the
events go: Page Load --> Process Events --> Page Prerender, so it's still
there at Prerender but is only still there on the next pass for Process
Events if you've put it back at page load (or it's stored in viewstate and
the framework has put it back for you).

If this doesn't do anything for you then post us a few snippets of what's
happening at Page Load, ItemDataBound, and UpdateCommand.

Bill

starwiz said:
I'm trying to use the DataGrid's editing with a DropDownList. I've
tried using every code sample I've seen and none of them seem to be
able to solve my problem.

When I call e.Item.FindControl("name-of-my-DropDownList"), where e is a
DataGridCommandEventArgs passed to the UpdateCommand of the DataGrid, I
get an empty DropDownList. In fact, when I call
e.Item.FindControl("name-of-a-label") in the non-editable portion of my
template, I get an empty label.

ASP.Net doesn't have a problem with my accessing the DropDownList from
methods that it calls, interestingly enough. I can see the contents of
the DropDownList just fine when it calls its PreRender method and I
access the method's sender.

This is really weird...can someone lend me a hand here?

I'd really appreciate it.

-Starwiz

Here's my datagrid code (with appologies in advance to anyone whose
newsreader doesn't format this nicely):

<asp:datagrid id="DataGrid" datakeyfield="ID" (and other parameters)>
<columns>
<asp:templatecolumn headertext="Status">
<itemtemplate>
<asp:label id="lblStatus" enableviewstate="True"
runat="server" text='<%#
((System.Data.DataRowView)Container.DataItem)[StatusField] %>'>
</asp:label>
</itemtemplate>
<edititemtemplate>
<asp:dropdownlist autopostback="False"
enableviewstate="True" runat="server" id="ddlStatus"
onprerender="SetStatusIndex" />
</edititemtemplate>
</asp:templatecolumn>
<asp:editcommandcolumn buttontype="LinkButton"
updatetext="Update" canceltext="Cancel"
edittext="Edit"></asp:editcommandcolumn>
<!--The rest of the columns are auto-populated-->
</columns>
</asp:datagrid>
*********************
And my C# code:

private bool bindDataGrid = false;
private void ViewAll_PreRender(object sender, System.EventArgs e)
{
if(bindDataGrid)
RefreshDataGrid();
}

private void RefreshDataGrid()
{
//...this code doesn't matter much
//but let me know if you want to see it.
}

protected string SelectedStatus = null;
private void DataGrid_EditCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
SelectedStatus = ((Label)e.Item.FindControl("lblStatus")).Text;
//SelectedStatus is always an empty string.

DataGrid.EditItemIndex = e.Item.ItemIndex;
bindDataGrid = true;
}

protected void SetStatusIndex(object sender, EventArgs e)
{
DropDownList ddl = (DropDownList)sender;
DataTable dt = DBAccessor.GetPatientStatuses();
foreach(DataRow dr in dt.Rows)
ddl.Items.Add(new ListItem((string)dr["Status"],
((int)dr["StatusID"]).ToString()));

ddl.SelectedIndex =
ddl.Items.IndexOf(ddl.Items.FindByValue(SelectedStatus));
}

private void DataGrid_UpdateCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
int index = e.Item.DataSetIndex;
DataTable dt = (DataTable)Session[PatientDT];
int id = (int)dt.Rows[index][IDField];
DropDownList ddl = (DropDownList)e.Item.FindControl("ddlStatus");

int newStatus = int.Parse(ddl.SelectedValue);
//ddl.SelectedValue is always an empty string.
//In fact, ddl.Items is empty, too;
//there aren't any meaningful properties
//of the ddl that I can read at all.

DBAccessor.SetPatientStatus(id, newStatus);
DataGrid.EditItemIndex = -1;
bindDataGrid = true;
}

//Yes, this is messy. It was a failed attempt
//at fixing this problem that I just haven't gotten
//rid of yet...
private void DataGrid_ItemDataBound(object sender,
System.Web.UI.WebControls.DataGridItemEventArgs e)
{
if(e.Item.ItemType == ListItemType.EditItem)
{
DropDownList ddl = (DropDownList)e.Item.FindControl("ddlStatus");
if(ddl != null)
SetStatusIndex(ddl, null);
}
else if(e.Item.ItemType == ListItemType.Item)
{
try
{
Label lbl = (Label)e.Item.FindControl("lblStatus");
lbl.Text =
(string)((System.Data.DataRowView)e.Item.DataItem)[StatusField];
}
finally {}
}
}
 
S

starwiz

Thanks for the quick reply, Bill.

The SetStatusIndex method fills the dropdownlist. It's called only by
the DataGrid's ItemDataBound event (when it's called for the row
containing the edititemtemplate) see DataGrid_ItemDataBound(). I've
also tried putting that method call in the DropDownList's PreRender
handler to no avail.

Anyway, SetStatusIndex() isn't called when you press the update link; I
just set a breakpoint there and checked it.

I'm not exactly sure what "snippets of what's happening at PageLoad"
etc. means, but I'll give you what I think you might be looking for:
When SetStatusIndex is called, I can see the DropDownList and all its
properties just fine. However, when DataGrid_UpdateCommand and
DataGrid_EditCommand are called, the DropDownList and the Label show no
values for significant properties (like Items, SelectedValue, or Text).
The objects aren't null, but they certainly don't contain the
information I want.

Is that what you were looking for? If it's not, I'm happy to provide
you with whatever information you think would be helpful.
Thanks again,
-Starwiz
 
G

Guest

Are you rebinding the data to the grid on *each* postback? Also, where are
you getting the data that SetStatusIndex uses to fill the list? Is it
hard-coded, or does it come from a datasource? In the latter case, is it
possible that you're rebinding the data on every postback, but on the passes
after the first you are not reloading the data, and are therefore binding to
an empty datasource (which doesn't cause errors, just gives you an empty
list).

If this doesn't ring any bells, post code snippets for SetStatusIndex,
ItemDataBound, and wherever you're calling .databind on the grid (e.g. Page
Load).

Bill
 
S

starwiz

I figured this one out a while ago, but I forgot to post my solution
here for posterity.

The problem was that I was using a LinkButton to submit the DataGrid's
updates. Since ASP.Net (and any other online application) is really
just server-generated HTML, the LinkButton is implemented by a
javascript call which refreshes the page. Because links cannot submit
forms, the changes to the drop down list were lost.

So there are two simple solutions: Either make the drop down list
automatically postback every time something in it changes (kind of
annoying, but works), or use regular buttons, rather than linkbuttons.

Hope this helps someone somehow,
-Starwiz
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top