have a GridView but cannot retrieve any of the data on post-back. I have set a break point at the start of Page_Init and Page_Load, on any post-back that is triggered the GridView.Rows.Count property is always 0. The GridView is defined as shown below:
<asp:GridView ID="TestGrid" runat="server" AllowSorting="False" DataKeyNames="ID,stock,percentage"
OnRowDataBound="GridViewTest_RowDataBound" EnableViewState="True"
OnRowUpdating="GridViewTest_OnRowUpdating" OnRowEditing="GridViewTest_OnRowEditing" OnRowCancelingEdit="GridViewTest_OnRowCancelingEdit"
AutoGenerateColumns="False">
<Columns>
<asp:CommandField ShowEditButton="True" CausesValidation="False"/>
<asp:BoundField DataField="Client" HeaderText="Client" InsertVisible="False" ReadOnly="True" />
<asp:BoundField DataField="Stock" HeaderText="Stock" InsertVisible="False" ReadOnly="True" />
<asp:BoundField DataField="DutyStatus" HeaderText="DutyStatus" InsertVisible="False" ReadOnly="True" />
<asp:TemplateField HeaderText="Percentage" InsertVisible="False">
<ItemTemplate>
<asp:Label ID="enhLbl" runat="server"><%#Eval("Percentage")%></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="TbPercentage" runat="server" Text="<%#Bind("Percentage")%>" class="edit-field"></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I have a check for IsPostBack in Page_Load and only bind the GridView to its DataSource if it's not a post-back.
The only other time it gets re-bound is in the GridViewTest_OnRowEditing, GridViewTest_OnRowUpdating and GridViewTest_OnRowCancelingEdit event handlers.
I am binding the GridView to a DataTable in the following way:
AGridView.DataSource = DataTableSplitParcels;
AGridView.DataBind();
AGridView.EnableViewState = true;
I don't know if it makes any difference, but the DataTable is created in code and the rows added within a loop.
Within Page_Load on a post-back I can see the GridView has its DataKeysArrayList property populated with the current values, however with it having no rows I am unable to retrieve any updated values.
The problem seems in the Page_Load event, which is refreshing your GridView with every call (irrespective of postback), and because of that you are losing what was entered by the user during update.
So put a debugger on your Page_Load and BindData events and see if it is getting called by Page_Load at all, and you need to stop that.. I tried a sample app and it worked at my end.. see below the code that I tried.
ASPX
<asp:GridView ID="TaskGridView" runat="server"
AutoGenerateEditButton="True"
AllowPaging="true"
OnRowEditing="TaskGridView_RowEditing"
OnRowCancelingEdit="TaskGridView_RowCancelingEdit"
OnRowUpdating="TaskGridView_RowUpdating"
OnPageIndexChanging="TaskGridView_PageIndexChanging">
</asp:GridView>
CS
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Create a new table.
DataTable taskTable = new DataTable("TaskList");
// Create the columns.
taskTable.Columns.Add("Id", typeof(int));
taskTable.Columns.Add("Description", typeof(string));
taskTable.Columns.Add("IsComplete", typeof(bool));
//Add data to the new table.
for (int i = 0; i < 20; i++)
{
DataRow tableRow = taskTable.NewRow();
tableRow["Id"] = i;
tableRow["Description"] = "Task " + i.ToString();
tableRow["IsComplete"] = false;
taskTable.Rows.Add(tableRow);
}
//Persist the table in the Session object.
Session["TaskTable"] = taskTable;
//Bind data to the GridView control.
BindData();
}
}
protected void TaskGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
//Retrieve the table from the session object.
DataTable dt = (DataTable)Session["TaskTable"];
//Update the values.
GridViewRow row = TaskGridView.Rows[e.RowIndex];
dt.Rows[row.DataItemIndex]["Id"] = ((TextBox)(row.Cells[1].Controls[0])).Text;
dt.Rows[row.DataItemIndex]["Description"] = ((TextBox)(row.Cells[2].Controls[0])).Text;
dt.Rows[row.DataItemIndex]["IsComplete"] = ((CheckBox)(row.Cells[3].Controls[0])).Checked;
//Reset the edit index.
TaskGridView.EditIndex = -1;
//Bind data to the GridView control.
BindData();
}
private void BindData()
{
TaskGridView.DataSource = Session["TaskTable"];
TaskGridView.DataBind();
}
Source available here
Related
I have 2 gridviews. The first one is visible and second one is not.
What I want is:- When I click on any row of the first gridview, the relevant data should get open in the another gridview.
I haven't done this before. Here is my html
<cc1:Grid ID="GridFirst" runat="server" FolderStyle="../Styles/Grid/style_12" AutoGenerateColumns="false"
AllowAddingRecords="false" AllowColumnResizing="true" Width="40%" ShowFooter="true"
ShowHeader="true" OnRowDataBound="GridFirst_RowDataBound" AllowRecordSelection="true">
<Columns>
<cc1:Column ID="Column1" DataField="Sr_NO" Wrap="true" ReadOnly="true" HeaderText="Sr No"
Width="4%">
</cc1:Column>
<cc1:Column ID="Column2" DataField="Type" Wrap="true" HeaderText="Type" Width="10%">
</cc1:Column>
<cc1:Column ID="Column3" DataField="Date" Wrap="true" HeaderText="Date" Width="10%">
</cc1:Column>
</Columns>
</cc1:Grid>
On GridFirst_RowDataBound event
protected void GridFirst_RowDataBound(object sender, Obout.Grid.GridRowEventArgs e)
{
// open second gridview with relevant data here
}
Use GridView SelectedValue property if your GridView has DataKeyNames property set as follows:
protected void grdClient_SelectedIndexChanged(object sender, EventArgs e)
{
if(grdClient.SelectedValue != null)
{
Project ObjProject = new Project();
int userClientID. = int .Parse(grdClient.SelectedValue.ToString());
ObjProject.UserClientID = userClientID;
grdProject.DataSource = ObjProject.GetProjectList();
grdProject.DataBind();
}
}
Initially make the second GridView visible false and OnRowClick make it visible true.
The RowDataBound event is fired each time a row has been filled with data (basically when you call gridview.DataBind());
It is not here you want to put the code to display the second gridview on a user event.
I think you should use RowCommand with a parameter.
In your aspx :
Add to your gridview :
OnRowCommand="myMethod_Rowcommand"
Try first with a clickable button on each row (and when you click on it, it will trigger the command), add these attributes :
CommandName="DisplaySecondGrid" CommandArgument='<%#Eval("yourId") %>'
Then in your code behind
if(e.CommandName == "DisplaySecondGrid")
{
var id = e.CommandArgument.ToString();
var myData = repository.GetData(id);
secondGridView.DataSource = myData;
secondGridView.DataBind();
secondGridView.Visible = true;
}
Something like this should do the trick
I have a GridView. Whenever I'm clicking on the LinkButton after selecting the Dropdown value, I'm getting only the first item of the Dropdown.
I need to show the selected value in TextBox. How can i get the desired value ?
This is my pseudo code:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" EnableModelValidation="True"
OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="ID">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%#Eval("ID")%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Count">
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" EnableViewState="true" AutoPostBack="false">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Button">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">LinkButton</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And the code behind:
protected void Page_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(string));
dt.Columns.Add("Count", typeof(string));
dt.Rows.Add("A", "5");
dt.Rows.Add("B", "8");
dt.Rows.Add("C", "4");
dt.Rows.Add("D", "7");
dt.Rows.Add("E", "9");
GridView1.DataSource = dt;
GridView1.DataBind();
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddl = (DropDownList)e.Row.FindControl("DropDownList1");
ddl.Items.Clear();
int count = Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, "Count").ToString());
List<string> list = new List<string>();
for (int i = 1; i <= count; i++)
{
list.Add(i.ToString());
}
ddl.DataSource = list;
ddl.DataBind();
}
}
protected void LinkButton1_Click(object sender, EventArgs e)
{
GridViewRow grdrow = (GridViewRow)((LinkButton)sender).NamingContainer;
DropDownList ddl = (DropDownList)GridView1.Rows[grdrow.RowIndex].FindControl("DropDownList1");
TextBox1.Text = ddl.SelectedValue.ToString();
}
Thanks in advance...
I'm going to guess that you should implement INotifyProperty change with the databinding. This way every change will be recorded including those made after first change in the drop down box. see ~ http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
Since you are dynamically creating and binding the Dropdownlist, it would not have loaded at the point your click event is executed. For you to use bound properties (the selectedValue property in this case), the control must already be loaded and it's viewstate info parsed and set by the control.
The databinding event that creates the dropdownlist runs after pre-render. See http://msdn.microsoft.com/en-us/library/ms178472%28v=vs.85%29.aspx for details on the page lifecycle.
To do what you are asking requires very close attention to the page life cycle. Try moving the code that sets the textbox to the GridView1_RowDataBound method. For this to work though, your control must be rendered with the same properties everytime (that way the event's on it are wired up correctly and the selectedValue property is set correctly).
Another alternative is to handle events on the textbox or dropdownlist itself. You would again have to pay attention to the properties and lifecycle of the control.
ASP.Net Forms uses the SmartUI pattern and IMHO this is the single greatest knock against this pattern.
Ok, try this
protected void LinkButton1_Click(object sender, EventArgs e)
{
LinkButton lnkBtn = (LinkButton)sender;
GridViewRow row = (GridViewRow)lnkBtn.NamingContainer;
DropDownList ddl= (DropDownList)row.FindControl("DropDownList1");
TextBox1.Text = ddl.SelectedValue.ToString();
}
I have searched a lot but couldn't find a solution to my problem.
With C#.Net, Asp.net 3.5 I have a 2 gridview controls in master child relation as following:
<asp:GridView ID="gridViewExistingSchedules"
runat="server" DataKeyNames="SchedulerId"
AutoGenerateColumns="false"
OnRowDataBound="gridViewExistingSchedules_RowDataBound"
OnRowCommand="gridViewExistingSchedules_RowCommand"
OnRowDeleting="gridViewExistingSchedules_RowDeleting">
<Columns>
<asp:TemplateField ItemStyle-Width="20px">
<ItemTemplate>
<asp:GridView
ID="gridViewSchedulerDetails"
runat="server"
AutoGenerateColumns="false"
DataKeyNames="SchedulerId">
<Columns>
<asp:BoundField DataField="DetailId" Visible="false" />
<asp:BoundField DataField="Survey" HeaderText="Survey" />
<asp:BoundField DataField="TimeDescription" HeaderText="Time" />
<asp:BoundField DataField="FromDate" HeaderText="From Date" />
<asp:BoundField DataField="ToDate" HeaderText="To Date" />
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="imgDelete" CommandArgument='<%# Bind("SchedulerId")%>' CommandName="Delete"
runat="server" ImageUrl="~/images/delete1.png" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="imgEdit" CommandArgument='<%# Bind("SchedulerId")%>' CommandName="Edit"
runat="server" ImageUrl="~/images/edit.png" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</ItemTemplate>
<ItemStyle Width="20px"></ItemStyle>
</asp:TemplateField>
<asp:BoundField DataField="Frequency" HeaderText="Frequency" />
<asp:BoundField DataField="DayOfWeek" HeaderText="Day Of Week" />
<asp:BoundField DataField="Time" HeaderText="Time" />
<asp:BoundField DataField="NextRunOn" HeaderText="Next Run On" />
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="imgDelete" CommandArgument='<%# Bind("SchedulerId")%>' CommandName="Delete"
runat="server" ImageUrl="~/images/delete.png" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Parent/master gridview "gridViewExistingSchedules" displays scheduled items where as child gridview "gridViewSchedulerDetails" displays details of a scheduled item (like which items were scheduled etc.)
I want to add a functionality, where a row in detailed gridview (i.e. gridViewSchedulerDetails can be deleted/edited. I have following code which handles row_deleting and row_command events:
protected void gridViewExistingSchedules_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int schedulerId = int.Parse(this.gridViewExistingSchedules.DataKeys[e.Row.RowIndex].Value.ToString());
GridView gvDetails = e.Row.FindControl("gridViewSchedulerDetails") as GridView;
gvDetails.RowCommand += new GridViewCommandEventHandler(gvDetails_RowCommand);
gvDetails.RowDeleting += new GridViewDeleteEventHandler(gvDetails_RowDeleting);
UICaller caller = new UICaller();
gvDetails.DataSource = caller.BindSchedulerDetails(schedulerId);
gvDetails.DataBind();
}
}
void gvDetails_RowCommand(object sender, GridViewCommandEventArgs e)
{
UIWriter writer = new UIWriter();
if (e.CommandName.Equals("Delete"))
{
int surveyDetailId = int.Parse(e.CommandArgument.ToString());
if (writer.RemoveSurvey(surveyDetailId))
{
this.labelUserNotification.Text = "Deleted successfully";
}
else
this.labelUserNotification.Text = "Due to some internal error, selected item cannot be deleted";
//bind existing scheduler
UICaller caller = new UICaller();
this.gridViewExistingSchedules.DataSource = caller.BindScheduler();
this.gridViewExistingSchedules.DataBind();
}
else if (e.CommandName.Equals("Edit"))
{
}
}
void gvDetails_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
}
With above given code there is run time exception:
"The GridView 'gridViewSchedulerDetails' fired event RowDeleting which wasn't handled."
First I thought that since being in parent/child relation master gridview need to handle the row_command event of child "gridViewSchedulerDetails" so I changed the code to:
void gvDetails_RowCommand(object sender, GridViewCommandEventArgs e)
{
}
void gvDetails_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
}
protected void gridViewExistingSchedules_RowCommand(object sender, GridViewCommandEventArgs e)
{
UIWriter writer = new UIWriter();
if (e.CommandName.Equals("Delete"))
{
int surveyDetailId = int.Parse(e.CommandArgument.ToString());
if (writer.RemoveSurvey(surveyDetailId))
{
this.labelUserNotification.Text = "Deleted successfully";
}
else
this.labelUserNotification.Text = "Due to some internal error, selected item cannot be deleted";
//bind existing scheduler
UICaller caller = new UICaller();
this.gridViewExistingSchedules.DataSource = caller.BindScheduler();
this.gridViewExistingSchedules.DataBind();
}
else if (e.CommandName.Equals("Edit"))
{
}
}
protected void gridViewExistingSchedules_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
}
But I am still getting same error given above.
Please advise how can I handle child gridview row delete even and what is actually happening here
You have specified that deleting event in your aspx code and that event handler is not there in your .cs file code that's why it creating problem. Either write a event handler like following.
void gridViewExistingSchedules_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
}
or remove following from your aspx code if you don't need that.
OnRowDeleting="gridViewExistingSchedules_RowDeleting"
Couple of things...
If you specify OnRowCommand="gridViewExistingSchedules_RowCommand" then technically this will catch the delete command too. therefore you can remove OnRowDeleting="gridViewExistingSchedules_RowDeleting" and catch it using a switch on command name. (see here http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.rowcommand%28v=vs.110%29.aspx)
That aside lets move on to the error.
The GridView 'gridViewSchedulerDetails' fired event RowDeleting which wasn't handled.
You are receiving this because the delete method is called on the gridview gridViewSchedulerDetails which is not being dealt with. You have 2 options to get rid of it.
Add an OnRowDeleting method to the child grid (gridViewSchedulerDetails) and handle that.
Add an OnRowCommand method to the child grid (gridViewSchedulerDetails) and handle that.
UPDATE
Just thought your image buttons contain the command name delete and edit... these are reserved for the events delete and edit and fire them respectively. As you are assigning different events in your databound this might be causing a conflict. Try changing the CommandName on your image buttons to del and ed in your child grid view and see if that helps.
I have GridView which filled with adapter:
OracleDataAdapter adapter = new OracleDataAdapter();
DataTable tableD = new DataTable();
adapter.SelectCommand = oracleCom;
adapter.Fill(tableD);
tableResults.DataSource = tableD.AsDataView();
tableResults.DataBind();
tableResults - it's a GridView.
I added the ability to change data in GridView:
tableResults.AutoGenerateEditButton = true;
tableResults.RowEditing += new GridViewEditEventHandler(tableResults_RowEditing);
tableResults.RowUpdating += new GridViewUpdateEventHandler(tableResults_RowUpdating);
tableResults.RowCancelingEdit += new GridViewCancelEditEventHandler(tableResults_RowCancelingEdit);
and now, from this:
when user push the Edit link he see this:
How to display current values in empty fields?
It's Addition:
<asp:GridView ID="tableResults" runat="server" DataMember="Table"
EnableModelValidation="True" CssClass = "GridViewStyle"
OnRowDeleting = "dataViewRowDeleting" AutoGenerateDeleteButton="True">
<HeaderStyle CssClass = "GridViewHeaderStyle" />
<RowStyle CssClass = "GridViewRowStyle"/>
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:HyperLink runat="server" Text="Скачать объект" NavigateUrl='<%#"objects/" + Eval("Идентификатор") %>'></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
You are just click on editing but you also have to rebind your gride view
Just bind your gridview again on gridview RowEditing event like this....
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
bindGridView1();
}
try this, this will help you definitely. if still you faces any problem than describe here with your issue...
I am now stuck. After spending ages trying to maintain dynamically added linkbutton or label to a gridview it seems I am overwriting a checkbox state on post back.
As stated I am dynamically adding either a linkbutton or a label to a place holder in a gridview with the following:
protected void LedgerGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int index = e.Row.RowIndex;
if (items[index].noteID > 0)
{
PlaceHolder label = (PlaceHolder)e.Row.FindControl("HasPrevious");
LinkButton link = new LinkButton();
link.CommandName = "LinkCommand";
link.Command += new CommandEventHandler(link_Command);
link.Text = "Yes";
link.ID = index.ToString();
label.Controls.Add(link);
}
else
{
PlaceHolder label = (PlaceHolder)e.Row.FindControl("HasPrevious");
Label noNote = new Label();
noNote.Text = "No";
label.Controls.Add(noNote);
}
Here is the gridview:
<asp:GridView runat="server" ID="LedgerGrid" AutoGenerateColumns="false"
onselectedindexchanged="LedgerGrid_SelectedIndexChanged"
onrowdatabound="LedgerGrid_RowDataBound" onrowcommand="LedgerGrid_RowCommand"
>
<Columns>
<asp:TemplateField HeaderText="Notes">
<ItemTemplate>
<asp:PlaceHolder ID="HasPrevious" runat="server"></asp:PlaceHolder>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Invoice Date" DataField="invoicedate" DataFormatString="{0:d}" />
<asp:BoundField HeaderText="Invoice" DataField="invoice" />
<asp:BoundField HeaderText="Fee Debt" DataField="Fee_Debt" DataFormatString="{0:C}" />
<asp:BoundField HeaderText="Cost Debt" DataField="Cost_Debt" DataFormatString="{0:C}" />
<asp:BoundField HeaderText="VAT Debt" DataField="VAT_Debt" DataFormatString="{0:C}" />
<asp:BoundField HeaderText="Total Debt" DataField="Total_Debt" DataFormatString="{0:C}" />
<asp:BoundField HeaderText="Client Code" DataField="ClientCode" />
<asp:ButtonField HeaderText="Matter Number" DataTextField="matternumber" CommandName="ViewMatter" />
<asp:BoundField HeaderText="Decription" DataField="matterdescription" />
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="AddInvoiceCheck" runat="server" Enabled="true" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
To make sure that my link button command works I am rebuilding the gridview as I would in the Page_load. Here is the page load:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string clientCode = Server.HtmlEncode(Request.QueryString["clientcode"]);
items = DataAccess.DataAccess.GetLedgerDetails(clientCode);
ViewState["LedgerItems"] = items;
ViewState["clientcode"] = clientCode;
LedgerGrid.DataSource = items;
LedgerGrid.DataBind();
LedgerClientObject clientDetails = DataAccess.DataAccess.GetClientDetails(clientCode);
ClientCodeLabel.Text = string.Format("Group Code: {0}", clientDetails.GroupCode);
ClientNameLabel.Text = string.Format("Client Name: {0}", clientDetails.ClientName);
ClientCodeFilter.DataSource = clientDetails.ClientCodes;
ClientCodeFilter.DataBind();
}
}
To maintain the dynamically added controls on post back I am calling the following:
protected void Page_PreLoad(object sender, EventArgs e)
{
if (IsPostBack)
{
items = (List<LedgerItem>)ViewState["LedgerItems"];
LedgerGrid.DataSource = items;
LedgerGrid.DataBind();
}
}
Of course it now seems that by using this method I am overwriting the state of the check-box gridview column. Am I approaching this all wrong? I would like to be able to use the viewstate to maintain the set up of my dynamically added controls to the gridview. Is there a way I can access the state of the checkbox control form gridview before/after I reload the gridview in PreLoad event?
I am checking the state of my checkbox column with a button click as follows:
protected void Unnamed1_Click(object sender, EventArgs e)
{
NoteModel note = new NoteModel();
for (int i = 0; i < LedgerGrid.Rows.Count; i++)
{
int invoice = Convert.ToInt32(LedgerGrid.Rows[i].Cells[2].Text);
CheckBox check = (CheckBox)LedgerGrid.Rows[i].FindControl("AddInvoiceCheck");
if (check.Checked)
{
note.invoices.Add(invoice);
}
}
if (note.invoices == null)
{
string clientcode = (string)ViewState["clientcode"];
ViewState["InvoiceError"] = 1;
Response.Redirect(string.Format("Ledger.aspx?clientcode={0}", clientcode));
}
else
{
string clientcode = (string)ViewState["clientcode"];
Session["NoteObject"] = note;
Response.Redirect(string.Format("AddNote.aspx?cc={0}", clientcode));
}
}
Whenever I iterate over the checkbox controls in the gridview they are all unchecked e.g overwritten by my PreLoad code!!!
In the end I decided not to use dynamically created controls. Instead I added a buttonfield to the grid view. In my rowdatabound event I then set the visibility of the button to false if it does meet my criteria. This way view state is maintained as i do not need to create control on post back.
Seems with webforms that avoiding dynamic controls where possible is the best bet. I would still like to know which event to tap into to override viewstate re-instating controls?