Gridview Row Events not firing in UserControl - c#

I've got a pretty strange problem with my usercontrols that I'm working with. I'm coding some user controls to be used in a DotNetNuke module.
Basically I have a UserControl on my page that holds some controls and then there is a Placeholder where I am loading in a UserControl that has a GridView placed in it.
Basically here is my page structure
<asp:Panel runat="server" ID="pnlServiceType" Visible="false">
<uc:ServiceType runat="server" ID="ServiceType" />
</asp:Panel>
Within that user control are some form elements and then the following:
<asp:PlaceHolder runat="server" ID="phServices" />
That placeholder then has a user control added to it like so:
<p class="header"><asp:Label runat="server" ID="lblServiceHeader" Font-Bold="true" /></p>
<asp:GridView runat="server" ID="gvServices" AlternatingRowStyle-BackColor="#eaeaea" BorderStyle="None" GridLines="None"
AutoGenerateColumns="false" CellPadding="6" Width="100%" EnableViewState="false" OnRowEditing="gvServices_RowEditing">
When the user picks something in the DropDownList, I'm clearing the controls out of the Placeholder, and re-adding just a single UserControl for the set of records for whatever type they've picked like so
_serviceID = e.Value;
//Clear the controls out of the placeholder
phServices.Controls.Clear();
//Reset the count of grids for the OnInit() method
Session["GridCount"] = 0;
if (e.Value != "NULL")
{
PopulateServicesGrid(_service.GetServicesByFormType(Convert.ToInt32(e.Value)));
}
else
{
PopulateServicesGrid(_service.GetServicesByClient(Convert.ToInt32(_client)));
}
And the PopulateServicesGrid method:
private void PopulateServicesGrid(List<NOAService> services)
{
//Creates a LINQ grouping based on the Billing Codes
//Allows a super easy creation of grids based on the grouped billing codes
var query = services.Select(service => service.BillingCode).Distinct();
foreach (string code in query)
{
var servicesByCode = services.Where(service => service.BillingCode == code).ToList();
ServicesGrid servicesGrid = LoadControl("~/DesktopModules/LEL Modules/NOA/ServicesGrid.ascx") as ServicesGrid;
Label lblServiceHeader = servicesGrid.FindControl("lblServiceHeader") as Label;
GridView gvServices = servicesGrid.FindControl("gvServices") as GridView;
phServices.Controls.Add(servicesGrid);
servicesGrid.ID = code;
lblServiceHeader.Text = servicesByCode[0].FormTypeName;
gvServices.DataSource = servicesByCode;
gvServices.DataBind();
Session["GridCount"] = phServices.Controls.Count;
}
}
And on my ServiceType UserControl, on the PageInit, I'm readding the ServiceGrid usercontrol so that my grids show up across postbacks and aren't lost from the Placeholder
void NOAServiceType_Init(object sender, EventArgs e)
{
for (int i = 0; i < Convert.ToInt32(Session["GridCount"]); i++)
{
ServicesGrid servicesGrid = LoadControl("~/DesktopModules/LEL Modules/NOA/ServicesGrid.ascx") as ServicesGrid;
phServices.Controls.Add(servicesGrid);
}
}
The grids populate successfully and everything seems to work just fine. But for some reason, on my GridView, I have a CommandField of
<asp:CommandField ShowEditButton="true" ItemStyle-HorizontalAlign="Right" EditText="Edit" UpdateText="Update"
EditImageUrl="~/images/LELModules/appbar.edit.rest.png" CancelImageUrl="~/images/LELModules/appbar.close.rest.png" UpdateImageUrl="~/images/LELModules/appbar.check.rest.png"
ButtonType="Image" CausesValidation="false" />
When I click my Edit command on the Grid row, nothing happens. My grid doesn't lose its rows, the control is still there, everything seems like it should be ok. The RowEditing event doesn't fire until I click it a second time.
Any idea why this might be occuring?
UPDATE: I've managed to figure out that my SelectedIndexChanged handlers are effectively resetting the DataSource on the Grid contained by the UserControl when they are readded to the PlaceHolder. When the CommandField (Edit) is clicked though, the Init fires for the UserControl that holds the placeholder
ServiceType UserControl < `Init` fires here
-Form elements
-Placeholder which holds
--UserControl with GridView
The Init method loads up new instances of the UserControl and adds them to the PlaceHolder, but the DataSource is null. With EnableViewState=true it looks like the data is still bound, but if I handle PreRender, I can see that the DataSource on my gvServices | null
Is it even possible to edit rows like this on a GridView that is being added dynamically to a PlaceHolder over and over?
FIXED I found out what the issue was after referring to this article
http://www.west-wind.com/weblog/posts/2006/Feb/24/Overriding-ClientID-and-UniqueID-on-ASPNET-controls
It got me thinking, what if the IDs were getting changed? The controls are way nested. So I went and put a watch on the GridView's ID, ClientID, and UniqueID just to see. When the Control is loaded on my Init handler, it's assigned a super generic ID when it's added.
private void PopulateServicesGrid(List<NOAService> services)
{
//Creates a LINQ grouping based on the Billing Codes
//Allows a super easy creation of grids based on the grouped billing codes
var query = services.Select(service => service.BillingCode).Distinct();
foreach (string code in query)
{
var servicesByCode = services.Where(service => service.BillingCode == code).ToList();
ServicesGrid servicesGrid = LoadControl("~/DesktopModules/LEL Modules/NOA/ServicesGrid.ascx") as ServicesGrid;
Label lblServiceHeader = servicesGrid.FindControl("lblServiceHeader") as Label;
GridView gvServices = servicesGrid.FindControl("gvServices") as GridView;
phServices.Controls.Add(servicesGrid);
**servicesGrid.ID = code;**
lblServiceHeader.Text = servicesByCode[0].FormTypeName;
gvServices.DataSource = servicesByCode;
gvServices.DataBind();
Session["GridCount"] = phServices.Controls.Count;
}
}
I was setting the ID as something else. So when I was hitting the Edit RowCommand on my grid, it was reloading the controls again on Init and the IDs were being changed back from my custom set code (T2020, pulled from my database) to the generic ID again, it didn't know how to fire the event.
I hope this helps someone as I've lost at least 12 hours fixing this problem.

Related

Datagrid ItemCommand event not firing

I am still a novice with asp.net, so I'm sure there are better ways to do some of this...
I want to allow a user to enter a date, and then execute an SQL query against a database to return all records matching that date. I want to display those records, and allow the user to select one for additional processing. It seemed like the DataGrid with a column of Pushbuttons was a good choice. In fact, I've done this before, but it those cases there was no user interaction involved. The page just ran a fixed SQL query. With what I'm doing now, the data is displayed as I want, but the Pushbuttons aren't working...the ItemCommand event doesn't fire.
I've read a lot of threads about the ItemCommand event not firing, but I still can't get this to work. My understanding is that I need to bind the DataGrid while not in a Postback, and I think my code does that. When I debug the Page_Load event, I can see that the code inside if (!IsPostBack){} is running, and the session variables have the expected data.
On the page that hosts the DataGrid, I have a 'Find' button that executes a SQL query against a database. The query uses a date entered into the textbox that is on that page. In the 'Find' button click event, I store the results of the query (a DataTable) in a session variable, then do a Redirect to re-load the page.
Once the page reloads, the session variables contain my expected data and the data is displayed in the DataGrid, along with the Pushbuttons. When I click any of the buttons in the DataGrid, the contents of the DataGrid disappear and the ItemCommand event does not fire.
Here's the definition of the DataGrid (updated to include the button):
<asp:Panel runat="server" ID="pnlSelect" HorizontalAlign="Left" Visible="true" style="margin-top:10px" >
Please select a participant.
<asp:DataGrid runat="server" ID="grdItems" AutoGenerateColumns="true" BorderColor="black" BorderWidth="1" CellPadding="3" style="margin-left:2px; margin-top:6px" OnItemCommand="grdSelect_ItemCommand" >
<Columns>
<asp:ButtonColumn HeaderStyle-HorizontalAlign="Center" ButtonType="PushButton" Text="Select" HeaderText="Select" CommandName="Select" >
<ItemStyle Width="60px" HorizontalAlign="Center"/>
</asp:ButtonColumn>
</Columns>
</asp:DataGrid>
</asp:Panel>
Here's the Page Load code (unneeded code-behind stuff is commented out):
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Session["y"] != null)
{
txtFind.Text = Session["x"].ToString();
DataTable table = Session["y"] as DataTable;
Session.Remove("x");
Session.Remove("y");
if (table != null)
{
/*
ButtonColumn buttonColumn = new ButtonColumn
{
HeaderText = "Select",
Text = "Select",
CommandName = "Select",
ButtonType = ButtonColumnType.PushButton,
};
grdItems.Columns.Add(buttonColumn);
foreach (DataColumn c in table.Columns)
{
BoundColumn column = new BoundColumn
{
HeaderText = c.Caption,
DataField = c.Caption,
ReadOnly = true
};
grdItems.Columns.Add(column);
}
*/
grdItems.DataSource = table;
grdItems.DataBind();
}
}
}
}
Here's the relevant 'Find' button event code. I can't post the details of the sql query text, but that part does work and the DataTable does contain the expected data:
DataTable table = DatabaseHelper.FindBySQL(sqlText);
if (table != null && table.Rows.Count > 0)
{
Session["x"] = searchtext;
Session["y"] = table;
Response.Redirect(Request.RawUrl, true);
}
And this the ItemCommand event. I place a breakpoint on the first line, and the debugger never hits it.
protected void grdItems_ItemCommand(object source, DataGridCommandEventArgs e)
{
string item = "";
switch (e.CommandName.ToLower())
{
case "select":
item = e.Item.Cells[1].Text.Trim();
//todo: handle the selected data
break;
}
}
Thanks for any thoughts.
Don

Bind a list of users controls to gridview

I desperately seeks in vain. I want to bind a List(T) of Users Controls (.ascx) to a gridview. I initialize my controls in code-behind :
List<myControl> ctrls = new List<myControl>();
myControl ctr = LoadControl("~/Control.ascx") as myControl;
ctr.Name = ...
// ...
ctrls.Add(myControl); // add new control to the collection
And after, i bind this list to Gridview control :
this.GridView1.DataSource = ctrls;
this.gridView1.DataBind();
In the Page_Load event with condition If (!IsPostBack). This does not work: the representation of the object is displayed. Whereas when I put the controls in a Panel, all worked.
Don't use a GridView for this. Use a Repeater. And bind it to the data, not to list of controls. Example:
<asp:Repeater runat="server" id="ControlsRepeater">
<ItemTemplate>
<uc:MyControl runat="server" />
</ItemTemplate>
</asp:Repeater>
Code Behind
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
var myData=GetData(); //should return some type of ICollection representing your data to bind to
ControlsRepeater.DataSource=myData;
ControlsRepeater.DataBind();
}
}
If you want paging, then you should take advantage of lazy loading (the Entity Framework handles this for you if you use that) and the Linq functions .Take() and .Skip().

ASP table row count not getting incremented

I have an ASP table, with a dropdownlist and text box in its 1st row. I have a button on click of which a similar row should be added. I have the following function in its button click event.
public void addRow()
{
int flag = Table1.Rows.Count;
DropDownList ddl = new DropDownList();
ddl.ID = "ddl" + (flag + 1).ToString();
TextBox tBox = new TextBox();
tBox.ID = "txt" + (flag + 1).ToString();
TableCell tCell1 = new TableCell();
TableCell tCell2 = new TableCell();
tCell1.Controls.Add(ddl);
tCell2.Controls.Add(tBox);
TableRow tRow = new TableRow();
tRow.Cells.Add(tCell1);
tRow.Cells.Add(tCell2);
Table1.Rows.Add(tRow);
}
This code works fine when adding 2nd row. When I click the button again, the value of flag which should have the value of number of rows of the table is not getting incremented. So a new row doesn't get created. Can you please tell me why the value of flag doesn't get incremented ? Or is their an easier way to do this ? Direct answer or link would be helpful.
Mark up code for Table:
<asp:Table ID="Table1" runat="server" Width="410px">
<asp:TableRow>
<asp:TableCell>
<asp:DropDownList runat="server" ID="ddl1"></asp:DropDownList>
</asp:TableCell>
<asp:TableCell>
<asp:TextBox runat="server" ID="txt1"></asp:TextBox>
</asp:TableCell>
</asp:TableRow>
</asp:Table>
Warning - Big ugly block of text
I'm going to try and explain why what you're trying to do is not as simple as it sounds (or as simple as I'd like it to be) and hopfully give you an alterantive approach, which while it
may not be straight forward, it should be "better".
It looks a high level overview of what you are trying to do is the following:
Give the user the oppotunity to add one or more records to a collection (database) before finalising the save.
It is possible to do this using postback to generate the additional rows/items beofore clicking the final save button. Hover this may not be the easiest, or best, way to do this.
From a technical viewpoint adding dynamic controls has to be handeld in a very specific manner at a specific point in the ASP.net page lifecylce. Dynamic controls also have to be recreated on every post back, so every time a user clicks the "add" button, you will have to re-reate the rows you already have in addition to the new row. This is why you only get the one row in this example. Thats just the adding of the dynaimc controls. Wait till you get to getting data from your dynamic text boxes and drop downs!
From an end users perspective, this approach is also not ideal as every time the user clicks the "add" button the page cycles through the request/response process, which at the minumun cuases a bit of an ugly flash.
Update
But how? I hear you ask. Well here it is (I've simplified it to one column for this example):
ASPX
<asp:Table ID="Table1" runat="server">
<asp:TableRow>
<asp:TableCell><asp:TextBox ID="txt1" runat="server"> </asp:TextBox></asp:TableCell>
</asp:TableRow>
</asp:Table>
<asp:Button ID="btnAdd" runat="server" Text="Add" onclick="Button1_Click" />
<asp:HiddenField ID="hdnRowCount" runat="server" />
<asp:Button ID="btnSave" runat="server" onclick="btnSave_Click" Text="Save" />
<div>
<asp:Label ID="lblResult" runat="server" Visible="false"></asp:Label>
</div>
C#
private int rowCount = 1;
private bool rowNeeded = false;
protected override void OnPreInit(EventArgs e)
{
//Pre-emptively create additional row on post back.
//We'll remove it if we don't need it later
//Controls Have to be added at pre-init to maintain their view state
//Adding a row in the button click event will result in any data
//entered in that row dissapearing from viewstate on next post back
if (IsPostBack)
{
//Get number of additional rows from hidden field
//We're using a hidden form field and Request.Form
//instead of ViewsState and hdnRowCount.value
//because ViewState has not been loaded at this stage
//of the page life cycle
if (!string.IsNullOrEmpty(Request.Form["hdnRowCount"]))
{
rowCount = int.Parse(Request.Form["hdnRowCount"]);
}
for (int i = 0; i < rowCount; i++)
{
TableRow tr = new TableRow();
TableCell tc = new TableCell();
TextBox tb = new TextBox();
// +2 as there are existing controls with "1", eg txt1
tb.ID = string.Format("txt{0}",i+2);
tc.Controls.Add(tb);
tr.Cells.Add(tc);
Table1.Rows.Add(tr);
}
}
base.OnPreInit(e);
}
//Add Row Click
protected void Button1_Click(object sender, EventArgs e)
{
//Hold number of additional rows in hidne field
hdnRowCount.Value = (++rowCount).ToString();
//Let the page know we need to keep the row
rowNeeded = true;
}
//An Exmple of how to get your data out
protected void btnSave_Click(object sender, EventArgs e)
{
string s = "";
//Iterate through the table rows finding the controls
//Using count -1 as we still have the pre-emptive row
for(int i = 0; i < Table1.Rows.Count-1; i++)
{
TextBox tb = (TextBox)Table1.Rows[i].FindControl(string.Format("txt{0}",i+1));
s += "," + tb.Text;
}
lblResult.Text = s;
lblResult.Visible = true;
}
protected override void OnLoadComplete(EventArgs e)
{
//Get rid of pre-emptive row if we don't need it
if (IsPostBack)
{
if (!rowNeeded)
{
Table1.Rows.RemoveAt(Table1.Rows.Count - 1);
}
}
base.OnLoadComplete(e);
}
End Update
So, how would I do it? Client side, is the answer to that question. I would use jQuery to create a clone of the first row. You then would need to adjust the id and name attributes of your form fields before appending your new row to the table. You would also need a hidden form field to keep track of the number of hidden rows. When your user finaly hits the "save" button, on the C# side, get the number of additional rows from you hidden field the go old school and use Request.Form[] to get the value of each of your added fields.
This, in my opionion, will be a smoother experience for the end user.
Another, somewhat hacky option,if you have a defined maximum number of additional rows. For this have the mamimum rows, with form controls in the table. You can then either use visible="false" in the aspx and use post back to change that to visible="true" when the user clicks "add". The other option there is to give the row a CSS class that hides the row and then use javascript/jquery to remove the class to make the row visible.
The issue here is that you are not understanding the ASP.Net Page Lifecycle and more importantly how it interacts with dynamic controls (your added controls.)
Unfortunately, we can not answer this question without understanding whether the values in these "dynamically" created controls are used server-side or client-side.
I can guess that:
1) If they are for client side consumption/usage, you are doing wrong. If you need more info ask another (more specific) question.
2) If they are for server side consumption/usage, you must only allow one new record per postback, and should include a "Save" button that will save the current "new" row and cause a page refresh that the user can add a new entry to.
3) See rule #0 (Every rule has exceptions. {This rule applies in so far that you understand the problem at hand.})
Monk

data pager in listview Issue

I have a listview where in I placed datapager as follows.
I am using SQl datasource and binding the records to ListView.
asp:ListView runat="server" ID="ListView1" DataKeyNames="ProductId,GameName" DataSourceID="GameTable" OnItemCommand="On_Select_Item"
and datapager in the LayoutTemplate
And in the item template I am placing a button, when clicked it calls a method where i am trying to fetch DatakeyName values. It is working fine in first page when pager is given, However when moved to other page in the pager, it is throwing me an exception.
Here is the button click code,
protected void On_Select_Item(object sender, ListViewCommandEventArgs e)
{
if (String.Equals(e.CommandName, "AddtoCart"))
{
//checks if the user is logged in
if (User.Identity.IsAuthenticated)
{
ListViewDataItem dataItem = (ListViewDataItem)e.Item;
DropDownList dl = e.Item.FindControl("DropDownList") as DropDownList;
String val="";
if (dl != null)
{
val = dl.SelectedValue; //Get the selected value from DropDownList
}
String price = Convert.ToString(e.CommandArgument).Trim(); //Get the price for the selected game.
-------------Exception is thrown at below line ---------
string ProductId =
ListView1.DataKeys[dataItem.DataItemIndex]["ProductId"].ToString(); //Product Id for the selected game.
string GameName = ListView1.DataKeys[dataItem.DataItemIndex]["GameName"].ToString(); //gamename
...............................
.............................
}
Define a grid first (you can change the control name to listView but the implementation is the same )
<asp:GridView runat="server" ID="grdResult"
CellPadding="2"
OnPageIndexChanging="grdResult_PageIndexChanging"
GridLines="None"
Width="100%"
AllowSorting="True"
AllowPaging="True"
Then in the bottom define a data source
<asp:SqlDataSource ID="sqlGridData" runat="server"></asp:SqlDataSource>
now in the code behind load your sqlGridData control with data (it accepts many parameters like datatable, odbcrecordset you can use .provider property mentioned here http://tinyurl.com/bllyjsz ) if you have static data them you even mention at the design time (as done here http://tinyurl.com/c8b6mbh)
private void BindDataGrid()
{
sqlGridData.Provider = dataReader;
grdResult.DataSourceID = "xmlGridData";
//grdResult.PageIndex = 0;
}
Try this and do let me know if you have any query.

GridView RowUpdating does not get the new values

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 DropDownLists 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 TemplateFields 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!
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 what TaskGridViewResult is either -- is this an event for GridViewResult? Do you have another GridView on your page, and you want to show GridViewResult based on some search criteria?
I'm also not sure why you put all of your GridView binding code in Page_Load. I see that you're checking GetPostBackControl to find the control that caused the PostBack -- this is a code smell. If your users have to click a specific "Search" button, you should isolate your GridView binding code within that button's Click event.
Anyway, as to TaskGridViewResult_RowUpdating:
It looks like you're trying to update GridViewResult's old values to the new values by setting its DataSource and then iterating through its data. You can't do that. What happens when you change your RowUpdating event to:
protected void TaskGridViewResult_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
GridViewResult.DataSource = (DataTable)Session["Result"];
GridViewResult.DataBind();
}
Now, other asides:
Your switch statements are code smells. DropDownLists expose a property called SelectedValue -- if you have some default value that isn't a valid selection (like the first option in your DropDownList), then you can change your original code from:
if ((test.ID == "SumbitSearch") && (DropDownListFrom.Text != "") && (DropDownListTo.Text != "") && (SearchField.Text != ""))
{
string from = string.Empty;
string to = string.Empty;
switch (DropDownListFrom.SelectedIndex)
{
case 0:
from = DropDownListFrom.Items[0].Value;
break;
/* other cases */
}
switch (DropDownListTo.SelectedIndex)
{
case 0:
to = DropDownListTo.Items[0].Value;
break;
/* other cases */
}
/* snip */
}
to:
if (test.ID == "SubmitSearch" && DropDownListFrom.SelectedIndex > 0 && DropDownListTo.SelectedIndex > 0 && SearchField.Text != "")
{
string from = DropDownListFrom.SelectedValue;
string to = DropDownListTo.SelectedValue;
/* snip */
}
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 to IsNullOrWhiteSpace(), 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 the Session variable with that new data.
- The MSDN code has a BindData() function -- I'm not sure if this is what your DataBind() function is, however.
- The MSDN code updates the GridView by re-binding the GridView to the appropriate data in the Session.
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 my RowUpdating event, I'd use e.Row.FindControl("controlName"), and update the Session 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 GridViews. 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 one GridView, you can always set its Visible property to false. Then, when you're ready to show it, set Visible = true.
Finally, I've spread my GridView code across so many events (button clicks, RowDataBound events from other GridViews/Repeaters, etc.), I can't imagine why someone would suggest that you only put it in Page_Load.

Categories

Resources