I have at the moment a problem with RowUpdating
from a GridView
and accessing the new values. I add a dynamic DataTable
to my GridView.DataSource
and bind to it. If I use the update button nothing happens and I get back to my normal GridView
.
Here's my Page_Load event:
protected void Page_Load(object sender, EventArgs e)
{
Control test = GetPostBackControl(Page);
if (Page.IsPostBack)
{
if ((test.ID == "SumbitSearch") && (DropDownListFrom.Text != "") && (DropDownListTo.Text != "") && (SearchField.Text != ""))
{
DataTable result = new DataTable();
string from = null;
string to = null;
switch (DropDownListFrom.SelectedIndex)
{
case 0:
from = DropDownListFrom.Items[0].Value;
break;
case 1:
from = DropDownListFrom.Items[1].Value;
break;
case 2:
from = DropDownListFrom.Items[2].Value;
break;
}
switch (DropDownListTo.SelectedIndex)
{
case 0:
to = DropDownListTo.Items[0].Value;
break;
case 1:
to = DropDownListTo.Items[1].Value;
break;
case 2:
to = DropDownListTo.Items[2].Value;
break;
}
result = LoadGridView(from, to);
GridViewResult.DataSource = result;
Session["Result"] = result;
GridViewResult.DataBind();
GridViewResult.Columns[0].Visible = true;
GridViewResult.Columns[1].Visible = true;
GridViewResult.HeaderRow.Cells[0].Width = Unit.Pixel(110);
GridViewResult.HeaderRow.Cells[1].Width = Unit.Pixel(60);
GridViewResult.HeaderRow.Cells[3].Text = "Nach: " + from;
GridViewResult.HeaderRow.Cells[4].Text = "Von: " + to;
}
}
else
{
GridViewResult.DataBind();
}
}
Later, the GridView
should only appear if both DropDownList
s are used and the SearchField
is not empty. I also check if the button which execute the PostBack
is the search button.
Here is what I added to the RowUpdating EventHandler
:
protected void TaskGridViewResult_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
GridViewResult.DataSource = (DataTable)Session["Result"];
for (int i = 0; i < GridViewResult.Columns.Count; i++)
{
DataControlFieldCell cell = GridViewResult.Rows[e.RowIndex].Cells[i] as DataControlFieldCell;
GridViewResult.Columns[i].ExtractValuesFromCell(e.NewValues, cell, DataControlRowState.Edit, true);
}
GridViewResult.EditIndex = -1;
DataBind();
}
What is going wrong?
Last Change: More Information (@jwiscarson)
I’m sorry, I was in hurry. I will try to give you a better view.
In that project, the users could select 2 categories, enter a search string and the result will show in a GridView. The RowUpdating stuff is for the "admin user".
Here is my problem, if the "admin user" click on edit, change the value of the cell and execute the update, the value would not changed in the DataTable
.
Without seeing your markup, it's hard for […] based on some search
criteria?
I add GridViewResult
as markup in my project.
I'm also not sure why […] within that button's Click event.
Yes, I thought that too! But I read in a blog it is better to put the code into Page_Load(), if you are working with GridViews
. I believed him. Is it okay, to put that code into the click event handler from my button? I'm very new to that. I just could read lots of blogs, msdn and ask here.
TaskGridViewResult_RowUpdating
is also added as markup to my code. Could I also create this and the GridView in my CreateChildControls()
?
As markups I have two DropDownLists
, a TextBox
for the search string, a search submit Button
and the GridView
.
At the moment, i havent the exactly code here but the GridView
looks like:
<asp:GridView ID="GridView1" runat="server"
OnRowUpdating="TaskGridViewResult_RowUpdating">
<!-- // More of that... -->
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:CommandField ShowDeleteButton="True" />
</Columns>
</asp:GridView>
I could give you more details tomorrow.
Maybe I forgot this. Before I could click the update button and execute the TaskGridViewResult_RowUpdating
event to change the value of the cell. I set the row editable with:
protected void TaskGridViewResult _RowEditing(object sender, GridViewEditEventArgs e)
{
GridViewResult.EditIndex = e.NewEditIndex;
DataBind();
}
Next Change:
I added to the GridView few TemplateField
s like:
<asp:TemplateField HeaderText="test">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("from") %>'> </asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("from") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
This is it, I have access to the new value with:
string test = ((TextBox)row.FindControl("TextBox1")).Text;
in TaskGridViewResult_RowUpdating()
Now, I just have to bind the template dynamically with the values from the dropdown list, and that’s it I think.
Thanks!
Best Answer
Hoo boy.
You didn't ask this in your question, but you've written some smelly code here. I'll try to address your question, but I'm also going through some of the other problems here.
Without seeing your markup, it's hard for me to tell if you've created
GridViewResult
programmatically or if it's in your markup as well. I'm not exactly sure whatTaskGridViewResult
is either -- is this an event forGridViewResult
? Do you have anotherGridView
on your page, and you want to showGridViewResult
based on some search criteria?I'm also not sure why you put all of your
GridView
binding code inPage_Load
. I see that you're checkingGetPostBackControl
to find the control that caused thePostBack
-- this is a code smell. If your users have to click a specific "Search" button, you should isolate yourGridView
binding code within that button'sClick
event.Anyway, as to
TaskGridViewResult_RowUpdating
:It looks like you're trying to update
GridViewResult
's old values to the new values by setting itsDataSource
and then iterating through its data. You can't do that. What happens when you change yourRowUpdating
event to:Now, other asides:
Your
switch
statements are code smells.DropDownList
s expose a property calledSelectedValue
-- if you have some default value that isn't a valid selection (like the first option in yourDropDownList
), then you can change your original code from:to:
If you can, please post your markup. I can offer you some more specific help or advice if I can tell what
Controls
you have on your page, and how they interact.Edit: I should also add that you should get in the habit of using
String.IsNullOrEmpty(string variable)
, rather than comparing to""
. Although this isn't as big of a problem when you're referencing the text from web controls, getting in the habit now will prevent you from serious headaches and inefficiently checking for null and empty later. If you're in .NET 4.0, you should have access toIsNullOrWhiteSpace()
, which is (in my opinion) more useful on the web, where users are more likely to try to enter junk data.Edit 2: In response to your additional details above:
In your
RowUpdating
event, you need to pull the new values out of the front-end controls, and then re-bind your data. It looks like your source code is pretty close to the MSDN source code here. The difference between your code and the code on MSDN is: - The MSDN code takes the new data from the edited row and updates the appropriate data in theSession
variable with that new data. - The MSDN code has aBindData()
function -- I'm not sure if this is what yourDataBind()
function is, however. - The MSDN code updates theGridView
by re-binding theGridView
to the appropriate data in theSession
.Frankly, I have some issues with the MSDN code. I really, really hate seeing code like:
dt.Rows[row.DataItemIndex]["Id"] = ((TextBox)(row.Cells[1].Controls[0])).Text;
To me, this is garbage, because it's so highly coupled to the order of your cells.If I had written the code, I would explicitly create all the front-end controls and use a binding command (if you aren't familiar, it looks like
<%# DataBinder.GetPropertyValue(Container.DataItem, "FieldName") %>
in the markup -- see more details here). Then, in myRowUpdating
event, I'd usee.Row.FindControl("controlName")
, and update theSession
data from that.Honestly, if your back-end data isn't changing on a regular basis, I don't see any reason to programmatically create your
GridView
s. It over-complicates your C# code to go through these steps yourself when you can just set it up once in your markup. If you need to hide oneGridView
, you can always set itsVisible
property tofalse
. Then, when you're ready to show it, setVisible = true
.Finally, I've spread my
GridView
code across so many events (button clicks,RowDataBound
events from otherGridViews
/Repeaters
, etc.), I can't imagine why someone would suggest that you only put it inPage_Load
.