On a RadGrid I can use the CommandItemTemplate to define my own buttons for, in my case, Save and Cancel the edit (like below)
<CommandItemTemplate>
<div style="padding: 5px 5px;">
<asp:LinkButton ID="btnUpdateEdited" runat="server" CommandName="UpdateEdited">Update</asp:LinkButton>
<asp:LinkButton ID="btnCancel" runat="server" CommandName="CancelAll">Cancel editing</asp:LinkButton>
</div>
</CommandItemTemplate>
On the code behind, I set up the ItemCommand.
> protected void RadGrid1_ItemCommand(object sender, GridCommandEventArgs e)
{
if (e.CommandName.CompareTo("UpdateEdited") == 0)
{
var commandItem = ((GridCommandItem)e.Item);
//Updade code here.
}
}
How can I access the modified row with the modified fields so I can perform an updade?
You should have them in command item and you can access them like this:
GridDataItem item = (GridDataItem)e.Item;
string value = item["ColumnUniqueName"].Text;
Is this what you want ? Just a sample you might need to modify it..
.aspx
<telerik:RadGrid ID="rg" runat="server" AutoGenerateColumns="false"
OnNeedDataSource="rg_NeedDataSource" OnItemCommand="rg_ItemCommand"
MasterTableView-CommandItemDisplay="Top" OnItemDataBound="rg_ItemDataBound">
<MasterTableView EditMode="InPlace">
<CommandItemTemplate>
<div style="padding: 5px 5px;">
<asp:LinkButton ID="btnUpdateEdited" runat="server"
CommandName="UpdateEdited">Update</asp:LinkButton>
<asp:LinkButton ID="btnCancel" runat="server"
CommandName="CancelAll">Cancel editing</asp:LinkButton>
</div>
</CommandItemTemplate>
<Columns>
<telerik:GridTemplateColumn>
<ItemTemplate>
<asp:Label ID="lbl" runat="server"
Text='<%# Eval("A") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txt" runat="server"
Text='<%# Eval("A") %>'></asp:TextBox>
</EditItemTemplate>
</telerik:GridTemplateColumn>
<telerik:GridTemplateColumn>
<ItemTemplate>
<asp:LinkButton ID="btnEdit" runat="server" Text="Edit"
CommandName="Edit"></asp:LinkButton>
</ItemTemplate>
<EditItemTemplate> </EditItemTemplate>
</telerik:GridTemplateColumn>
</Columns>
</MasterTableView>
</telerik:RadGrid>
.cs
protected void Page_Load(object sender, EventArgs e)
{
// Check
if (!IsPostBack)
{
// Variable
DataTable dt = new DataTable();
dt.Columns.Add("A");
dt.Rows.Add("A1");
// Check & Bind
if (dt != null)
{
// Viewstate
ViewState["Data"] = dt;
rg.DataSource = dt;
rg.DataBind();
dt.Dispose();
}
}
}
protected void rg_NeedDataSource(object sender, GridNeedDataSourceEventArgs e)
{
rg.DataSource = ViewState["Data"] as DataTable;
}
protected void rg_ItemCommand(object sender, GridCommandEventArgs e)
{
// Check
if (e.CommandName == "UpdateEdited")
{
// Variable
DataTable dt = new DataTable();
dt.Columns.Add("A");
// Loop All
foreach (GridEditableItem item in rg.Items)
{
// Find Control
TextBox txt = item.FindControl("txt") as TextBox;
// Check & Add to DataTable
if (txt != null) dt.Rows.Add(txt.Text.Trim());
}
// Check
if (dt != null && dt.Rows.Count > 0)
{
// Set Viewstate
ViewState["Data"] = dt;
// Bind
rg.DataSource = dt;
rg.DataBind();
// Dispose
dt.Dispose();
}
}
else if (e.CommandName == "CancelAll")
{
// Clear Edit Mode
rg.MasterTableView.ClearChildEditItems();
// Rebind
rg.Rebind();
}
}
protected void rg_ItemDataBound(object sender, GridItemEventArgs e)
{
// Check
if (e.Item is GridCommandItem)
{
// Find Control
LinkButton btnUpdateEdited = e.Item.FindControl("btnUpdateEdited") as LinkButton;
LinkButton btnCancel = e.Item.FindControl("btnCancel") as LinkButton;
// Get is Edit Mode ?
if (rg.EditIndexes.Count > 0)
{
if (btnUpdateEdited != null) btnUpdateEdited.Visible = true;
if (btnCancel != null) btnCancel.Visible = true;
}
else
{
if (btnUpdateEdited != null) btnUpdateEdited.Visible = false;
if (btnCancel != null) btnCancel.Visible = false;
}
}
}
Related
Data in my GridView inside an UpdatePanel is going out of synch with the database and I can't figure out why. This has resulted in incorrect updates to the database which I have to fix rapidly! Can anyone help?
I have multiple UpdatePanels that have GridViews inside that can be edited by the user. There is a search feature and filter buttons that select queried data from the database and display in the GridView. There is sorting enabled and the "out of synchness" occurs mostly when sorting and then editing a field.
The data comes from a SQL Database. I can update the data directly through OnTextChange option of my TemplateField like this:
<asp:GridView
ID="GridView4"
runat="server"
OnSorting="TaskGridView_Sorting"
AllowSorting="True"
Width="100%" >
<Columns>
<asp:TemplateField SortExpression="name" HeaderText="Name">
<HeaderStyle HorizontalAlign="Left" CssClass="col_name" />
<ItemTemplate>
<asp:TextBox ID="name" AutoPostBack="True" CssClass="col_name" runat="server" Text='<%# Eval("name") %>' Width=180 OnTextChanged="text_change" />
</ItemTemplate>
</asp:TemplateField>
...
I have my gridview inside an UpdatePanel that has these options:
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
...
I have enabled partial rendering like this:
<ajaxToolKit:ToolkitScriptManager EnablePartialRendering="true" runat="server" />
I have buttons that filter the data by requerying the database and displaying just the filtered data like this:
DataGrid_Load(DAL.Search_reg_log(OrgText.Text, searchText, searchCol), "reg");
The gridview gets its data loaded like this:
private void DataGrid_Load(DataTable command, string type)
{
DataTable dataTable = new DataTable();
dataTable = command;
string sortDir = ViewState["SortDirection"] as string;
string sortExp = ViewState["SortExpression"] as string;
if(ViewState["SortExpression"] != null)
{
dataTable = resort(dataTable, sortExp, sortDir);
}
try
{
var query = from c in dataTable.AsEnumerable()
where c.Field<string>("status") == "Invoiced" && c.Field<string>("reg_cat_id") != "Archive"
|| c.Field<string>("status") == "Confirmed" && c.Field<string>("reg_cat_id") != "Archive"
select c ;
if(query.Any()){
DataTable t2 = query.CopyToDataTable();
GridView4.DataSource = t2;
GridView4.DataBind();
} else {
GridView4.DataSource = new DataTable();
GridView4.DataBind();
}
}
catch(Exception e) {
ErrorText.Text = "Caught Exception: " + e;
}
...
I have isolated one cause of the data errors which occurs after sorting a column and then
protected void TaskGridView_Sorting(object sender, GridViewSortEventArgs e)
{
string sortExp = ViewState["SortExpression"] as string;
string sortDir = ViewState["SortDirection"] as string;
if(sortDir == "asc" & sortExp == e.SortExpression.ToString())
ViewState["SortDirection"] = "desc";
else
ViewState["SortDirection"] = "asc";
ViewState["SortExpression"] = e.SortExpression.ToString();
if(searchCol != "" && searchText != "")
DataGrid_Load(DAL.Search_reg_log(OrgText.Text, searchText, searchCol), "reg");
else
DataGrid_Load(DAL.reg_log(HeadText.Text, OrgText.Text), "reg");
UpdatePanels();
}
Here is the resort function:
public static DataTable resort(DataTable dt, string colName, string direction)
{
dt.DefaultView.Sort = colName + " " + direction;
dt = dt.DefaultView.ToTable();
return dt;
}
Please help with some direction of what might be causing this.
It looks like you are having some trouble with GridView and updating them. I will post a complete working example below. Start with that and gradually update that code to fit your own needs, like getting data with var query = from c in dataTable.AsEnumerable(). The important thing is to sort the data every time you (re)bind the GridView data. And I'm not sure what is happening inside resort, but you have to use dt.DefaultView.ToTable(); to save the sorting in the DataTable.
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:GridView ID="GridView1" runat="server"
DataKeyNames="ID" AllowSorting="true"
OnSorting="GridView1_Sorting"
AutoGenerateColumns="false"
AutoGenerateEditButton="true"
OnRowEditing="GridView1_RowEditing"
OnRowCancelingEdit="GridView1_RowCancelingEdit"
OnRowUpdating="GridView1_RowUpdating">
<Columns>
<asp:TemplateField HeaderText="ID" SortExpression="ID">
<ItemTemplate>
<%# Eval("ID") %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Name" SortExpression="name">
<ItemTemplate>
<%# Eval("name") %>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text=' <%# Eval("name") %>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Literal ID="Literal1" runat="server"></asp:Literal>
</ContentTemplate>
</asp:UpdatePanel>
Code behind
protected void Page_Load(object sender, EventArgs e)
{
//bind data in an ispostback check
if (!IsPostBack)
{
DataGrid_Load();
}
}
private void DataGrid_Load()
{
//load the datatable data
DataTable dt = source;
//check if the viewsstate existst
if (ViewState["SortExpression"] != null && ViewState["SortDirection"] != null)
{
//sort the datatable before binding it to the gridview
dt.DefaultView.Sort = ViewState["SortExpression"] + " " + ViewState["SortDirection"];
dt.DefaultView.ToTable();
}
//bind the sorted datatable to the gridvidw
GridView1.DataSource = dt;
GridView1.DataBind();
}
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
//load the previous sorting settigns
string sortExp = ViewState["SortExpression"] as string;
string sortDir = ViewState["SortDirection"] as string;
//reverse the direction if the column is the same as the previous sort
if (sortDir == "asc" & sortExp == e.SortExpression.ToString())
ViewState["SortDirection"] = "desc";
else
ViewState["SortDirection"] = "asc";
//put the current sort column in the viewstate
ViewState["SortExpression"] = e.SortExpression.ToString();
//rebind data
DataGrid_Load();
}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
//set the edit index and rebind data
GridView1.EditIndex = e.NewEditIndex;
DataGrid_Load();
}
protected void GridView1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
//reset the edit index and rebind data
GridView1.EditIndex = -1;
DataGrid_Load();
}
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
//use findcontrol to locate the textbox in the edit template
TextBox tb = (TextBox)GridView1.Rows[e.RowIndex].FindControl("TextBox1");
//get the id of the row from the datakeys
int id = Convert.ToInt32(GridView1.DataKeys[e.RowIndex].Values[0]);
//show result for testing
Literal1.Text = "ID: " + id + "<br>Name: " + tb.Text;
//reset the edit index and rebind data
GridView1_RowCancelingEdit(null, null);
}
aspx file:
<asp:Repeater ID="Repeater_sorular" runat="server">
<HeaderTemplate>
</HeaderTemplate>
<ItemTemplate>
<div class="div_soru">
<div class="div_soru_wrapper">
<%#Eval("Subject")%>
<asp:RadioButtonList ID="RadioButtonList_secenekler" runat="server" Visible='<%# Eval("TypeId").ToString() == "1" %>'
DataSource='<%#Eval("Secenekler")%>' DataTextField='<%#Eval("OptionName")%>' DataValueField='<%#Eval("OptionId")%>'>
</asp:RadioButtonList>
<asp:CheckBoxList ID="CheckBoxList_secenekler" runat="server" Visible='<%# Eval("TypeId").ToString() == "2" %>'
DataSource='<%#Eval("Secenekler")%>' DataTextField='<%#Eval("OptionName")%>' DataValueField='<%#Eval("OptionId")%>'>
</asp:CheckBoxList>
</div>
</div>
</ItemTemplate>
<FooterTemplate>
</FooterTemplate>
</asp:Repeater>
and codebehind:
SpAnketDataContext db = new SpAnketDataContext();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindRepeaterSorular();
}
}
protected void ImageButton_kaydet_OnCommand(object source, CommandEventArgs e)
{
}
private void BindRepeaterSorular()
{
int anket_id = 3;
var sorular = from soru in db.TableSurveyQuestions
where soru.SurveyId == anket_id
select new
{
soru.TypeId,
soru.Subject,
soru.QuestionId,
soru.SurveyId,
soru.QueueNo,
SurveyTitle = soru.TableSurvey.Title,
TypeName = soru.TableSurveyQuestionType.TypeName,
Secenekler = from secenekler in soru.TableSurveyOptions
select new
{
secenekler.OptionId,
secenekler.OptionName,
secenekler.QuestionId,
}
};
Repeater_sorular.DataSource = sorular;
Repeater_sorular.DataBind();
}
this is the code that I try to get values but I can get only last radiobuttonlist values.
protected void Repeater_sorular_ItemCommand(object sender, RepeaterCommandEventArgs e)
{
foreach (RepeaterItem item in Repeater_sorular.Items)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
CheckBoxList CheckBoxList1 = (CheckBoxList)e.Item.FindControl("CheckBoxList_secenekler");
RadioButtonList RadioButtonList1 = (RadioButtonList)e.Item.FindControl("RadioButtonList_secenekler");
if (CheckBoxList1 != null)
{
foreach (ListItem li in CheckBoxList1.Items)
{
TableSurveyVote votes=new TableSurveyVote();
votes.MemberId=1;
votes.OptionId=Int32.Parse(li.Value);
db.TableSurveyVotes.InsertOnSubmit(votes);
db.SubmitChanges();
}
}
if (RadioButtonList1 != null)
{
foreach (ListItem li in RadioButtonList1.Items)
{
TableSurveyVote votes=new TableSurveyVote();
votes.MemberId=1;
votes.OptionId=Int32.Parse(li.Value);
db.TableSurveyVotes.InsertOnSubmit(votes);
db.SubmitChanges();
}
}
}
}
}
What is wrong?
You get the same results as you say on the comment because you do not use the populate from the foreach loop (the item) but use the same reference e.Item on the loop.
I have an UpdatePanel, in it a GridView, and in it a Repeater. There is a button to add comment. This button post backs but id does not run the function code behind. Here is my code
<updatepanel>
<gridview>
<repeater>
<asp:Button ID="kitapVarYorumEkle" runat="server"
CommandArgument='<%#Eval("id") %>'
CommandName='<%# GridView1.Rows.Count.ToString() %>'
Text="Yorum ekle" class="blueButton"
OnClick="kitapVarYorumEkle_Click" />
</repeater>
</gridview>
</updatepanel>
Code inside the js is:
protected void kitapVarYorumEkle_Click(object sender, EventArgs e)
{
kitapVarYorum temp = new kitapVarYorum();
if (Session["id"] != null)
{
temp.uyeId = Convert.ToInt32(Session["id"]);
}
Button btn = (Button)sender;
temp.kitapVarId = Convert.ToInt32(btn.CommandArgument);
string text = "";
GridViewRow row = GridView1.Rows[Convert.ToInt32(btn.CommandName)];
if (row != null)
{
TextBox txt = row.FindControl("txtYorum") as TextBox;
if (txt != null)
{
text = txt.Text;
}
}
temp.icerik = text;
var db = Tools.DBBaglanti();
db.kitapVarYorums.InsertOnSubmit(temp);
db.SubmitChanges();
// Page.Response.Redirect(Page.Request.Url.ToString(), true);
}
}
I have tried it outside the the controls and it works
Have you tried the ItemCommand approach?
<asp:Button
CommandArgument='<%#Eval("id") %>'
CommandName="yourCommandNameOfChoice"
Text="Yorum ekle"
ID="kitapVarYorumEkle"
class="blueButton" runat="server"
OnClick="kitapVarYorumEkle_Click" />
now add an ItemCommand event for your repeater:
protected void yourRepeater_ItemCommand(object source , RepeaterCommandEventArgs e)
{
switch(e.CommandName)
{
case "yourCommandNameOfChoice":
// Your Code Here
break;
}
}
I have a gridView with 5 columns with Edit and Delete button on each row of GridView. Once an Edit button a particular row is clicked , I want to disable the edit and delete buttons on rest of the rows.
Below is my aspx
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" ShowFooter="True" EnableModelValidation="True" onrowdatabound="GridView1_RowDataBound" onrowcommand="GridView1_RowCommand" onrowdeleting="GridView1_RowDeleting" EditRowStyle-ForeColor="Aqua" onrowediting="GridView1_RowEditing" >
<asp:TemplateField HeaderText="Item#" >
<ItemTemplate>
<asp:Label ID="Item#" runat="server" Text='Label' ></asp:Label>
</ItemTemplate>
</asp:TemplateField>
..........
<asp:TemplateField >
<ItemTemplate>
<asp:Button ID="btnEdit" runat="server" CausesValidation ="false" Font-Size="Smaller" CommandName="Edit" Text="Edit" CommandArgument='<%# DataBinder.Eval(Container, "RowIndex") %>' Width="35px"/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField >
<ItemTemplate>
<asp:Button ID="btnDelete" runat="server" CssClass="GridButton" CausesValidation="False" CommandName="Delete" Font-Size="Smaller" Text="Delete" CommandArgument='<%# DataBinder.Eval(Container, "RowIndex") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
int x = Convert.ToInt32(e.CommandArgument.ToString());
txtLineItemNumber.Text = (x + 1).ToString();
}
else
{
int x = Convert.ToInt32(e.CommandArgument.ToString());
foreach (GridViewRow row in GridView1.Rows)
{
if (row.RowIndex != x)
{
Button editButton = (Button)row.FindControl("btnEdit");
editButton.Enabled = false;
Button deleteButton = (Button)row.FindControl("btnDelete");
deleteButton.Enabled = false;
}
else
{
Button deleteButton = (Button)row.FindControl("btnDelete");
deleteButton.Text = "Cancel";
e.CommandName = "Cancel"; --- This is not possible...what should I do so that the Command Name is changed to Cancel and it does the cancel operation.
}
} }
}
Please help me to get it working.....
The approach you are taking will work fine. However the CommandArgument which is set in your markup CommandArgument='<%# DataBinder.Eval(Container, "RowIndex") %>' is not a reference to the Button itsself but the index of the GridView row the Button resides in.
You will need to retrieve the index from the CommandArgument in the RowCommand event and then enable/disable all buttons on other rows like so:
void gridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
switch (e.CommandName.ToLower())
{
case "edit":
{
int rowIndex = Convert.ToInt32(e.CommandArgument);
foreach (GridViewRow row in gridView1.Rows)
{
if (row.RowIndex != rowIndex)
{
Button editButton = (Button)row.FindControl("btnEdit");
editButton.Enabled = false;
Button deleteButton = (Button)row.FindControl("btnDelete");
deleteButton.Enabled = false;
}
}
}break;
}
}
Edit (based on comment)
Try moving the code that modifies the delete button to the RowEditing event handler like so:
void gridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
gridView1.EditIndex = e.NewEditIndex;
DataBind();
Button deleteButton = (Button)gridView1.Rows[e.NewEditIndex].FindControl("btnDelete");
deleteButton.Text = "Cancel";
deleteButton.CommandName = "Cancel";
}
void gridView1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
gridView1.EditIndex = -1;
DataBind();
}
Hope this helps.
You could use javascript, outlined here, http://www.krissteele.net/blogdetails.aspx?id=92 . Add logic to not disable for the current row.
I have a GridView that includes BoundField and TemplateField elements. Some of the TemplateField elements are dynamically generated. For the sake of reference, here is the GridView that I am using
<asp:GridView ID="myGridView" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" ShowFooter="True" EnableModelValidation="True"
OnLoad="myGridView_Load" OnRowCommand="myGridView_RowCommand"
OnRowEditing="myGridView_RowEditing" OnRowDeleting="myGridView_RowDeleting"
OnRowCancelingEdit="myGridView_RowCancelingEdit"
OnRowUpdating="myGridView_RowUpdating">
<Columns>
<asp:BoundField DataField="Number" Visible="true" HeaderText="Test" />
<asp:TemplateField HeaderText="Number">
<EditItemTemplate>
<asp:TextBox ID="tb1" runat="server" Text='<%# Bind("Number") %>' />
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lb1" runat="server" Text='<%# Bind("Number") %>' />
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="ftb" runat="server" Text="[x]" />
</FooterTemplate>
</asp:TemplateField>
<%-- Dynamically Generated Columns Will Be Inserted Here --%>
<asp:TemplateField HeaderText="Actions">
<EditItemTemplate>
<asp:LinkButton ID="ulb" runat="server" Text="update" CommandName="Update" />
<asp:LinkButton ID="clb" runat="server" Text="cancel" CommandName="Cancel" />
</EditItemTemplate>
<FooterTemplate>
<asp:LinkButton ID="slb" runat="server" Text="insert"
OnClick="saveLinkButton_Click" />
</FooterTemplate>
<ItemTemplate>
<asp:LinkButton ID="elb" runat="server" Text="edit" CommandName="Edit" />
<asp:LinkButton ID="dlb" runat="server" Text="delete" CommandName="Delete" />
</ItemTemplate>
</asp:TemplateField
</Columns>
<EmptyDataTemplate>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td>Number</td></tr>
<tr>
<td><asp:TextBox ID="ntb" runat="server" /></td>
<td><asp:LinkButton ID="slb2" runat="server" Text="save" OnClick="saveLinkButton_Click" /></td>
</tr>
</table>
</EmptyDataTemplate>
</asp:GridView>
When the GridView initially loads, everything is loaded properly. However, anytime I perform a command (edit, insert, delete), all of the data goes away. Oddly, the BoundField values still appear correctly. However, any TemplateField does not seem to get rendered. The code that I am using to work with this GridView is here:
public partial class GridView : System.Web.UI.Page
{
private List<string> dynamicColumnNames = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
LoadPageData();
}
protected void saveLinkButton_Click(object sender, EventArgs e)
{
}
protected void myGridView_Load(object sender, EventArgs e)
{
if (Page.IsPostBack == false)
{
BindGridData();
}
}
protected void myGridView_RowCommand(object sender, GridViewCommandEventArgs e)
{ }
protected void myGridView_RowEditing(object sender, GridViewEditEventArgs e)
{
myGridView.EditIndex = e.NewEditIndex;
BindGridData();
}
protected void myGridView_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
LoadPageData();
BindGridData();
}
protected void myGridView_RowCancelingEdit(object sender, EventArgs e)
{
myGridView.EditIndex = -1;
BindGridData();
}
protected void myGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
myGridView.EditIndex = -1;
LoadPageData();
BindGridData();
}
private void BindGridData()
{
// Create a temporary data source
DataTable tempData = new DataTable();
tempData.Columns.Add("ID");
tempData.Columns.Add("Number");
// Dynamically add template columns
foreach (string columnName in dynamicColumnNames)
{
tempData.Columns.Add(columnName);
TemplateField templateField = new TemplateField();
templateField.HeaderTemplate = new MyTemplateField(ListItemType.Header, columnName);
templateField.ItemTemplate = new MyTemplateField(ListItemType.Item, columnName);
templateField.EditItemTemplate = new MyTemplateField(ListItemType.EditItem, columnName);
templateField.FooterTemplate = new MyTemplateField(ListItemType.Footer, columnName);
myGridView.Columns.Insert(2, templateField);
}
// Add some phony data
Random random = new Random(DateTime.Now.Millisecond);
for (int i = 0; i < 10; i++)
{
DataRow tempRow = tempData.NewRow();
tempRow["Number"] = (i + 1);
foreach (string column in dynamicColumnNames)
tempRow[column] = random.NextDouble();
tempData.Rows.Add(tempRow);
}
// Bind the data to the grid
myGridView.DataSource = tempData;
myGridView.DataBind();
}
private void LoadPageData()
{
dynamicColumnNames.Add("USA");
dynamicColumnNames.Add("Japan");
dynamicColumnNames.Add("Mexico");
}
}
internal class MyTemplateField : ITemplate
{
// The type of the list item
private ListItemType listItemType;
// The value to use during instantiation
private string value1 = string.Empty;
public MyTemplateField(ListItemType listItemType, string value1)
{
this.listItemType = listItemType;
this.value1 = value1;
}
public void InstantiateIn(Control container)
{
if (listItemType == ListItemType.Item)
{
TextBox textBox = new TextBox();
textBox.ReadOnly = true;
textBox.DataBinding += new EventHandler(textBox_DataBinding);
container.Controls.Add(textBox);
}
else if (listItemType == ListItemType.EditItem)
{
TextBox textBox = new TextBox();
textBox.DataBinding += new EventHandler(textBox_DataBinding);
container.Controls.Add(textBox);
}
else if (listItemType == ListItemType.Header)
{
Literal literal = new Literal();
literal.Text = value1;
container.Controls.Add(literal);
}
else if (listItemType == ListItemType.Footer)
{
TextBox textBox = new TextBox();
container.Controls.Add(textBox);
}
}
private void textBox_DataBinding(object sender, EventArgs e)
{
TextBox textBox = (TextBox)(sender);
GridViewRow row = (GridViewRow)(textBox.NamingContainer);
textBox.Text = DataBinder.Eval(row.DataItem, value1).ToString();
}
}
How do I use commands in a GridView with Dynamically added columns? What is wrong with my code?
Thank you!
Dynamically added controls must be added on each post, you can't just add these controls on the first page load. Try removing your BindGridData() from within the Page.IsPostBack == false.