I have an editable GridView.
I have an AddRow button, which adds a row which consists of 3 text boxes and one dropdown list.
Also, I have a Delete button, which removes the whole row when clicked.
Whenever I click on AddRow button, the selection of my dropdownlist doesn't persist, the selected value is realigned to the very first item.
Below are the codes:
<asp:GridView ID="GridView1" runat="server" ShowFooter="true" AutoGenerateColumns="false"
OnRowDeleting="GridView1_RowDeleting">
<Columns>
<asp:TemplateField HeaderText="Serial No">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Container.DataItemIndex + 1 %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Col1">
<ItemTemplate>
<asp:TextBox runat="server" ID="txt1" Text='<%# Eval("Column1") %>'></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Col2">
<ItemTemplate>
<asp:TextBox ID="txt2" runat="server" Text='<%# Eval("Column2") %>'></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Col3">
<ItemTemplate>
<asp:TextBox ID="txt3" runat="server" Text='<%# Eval("Column3") %>'></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="DropDown">
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" DataTextField='<%# Eval("Column4") %>'>
<asp:ListItem>London</asp:ListItem>
<asp:ListItem>Paris</asp:ListItem>
<asp:ListItem>New Delhi</asp:ListItem>
<asp:ListItem>New York</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
<FooterStyle HorizontalAlign="Right" />
<FooterTemplate>
<asp:Button ID="btnAddNewRow" runat="server" Text="AddRow" OnClick="Add" />
</FooterTemplate>
</asp:TemplateField>
<asp:CommandField ButtonType="Button" ShowDeleteButton="true" />
</Columns>
</asp:GridView>
<asp:Button ID="btnSavetoDB" runat="server" Text="save" OnClick="btnSavetoDB_Click" />
EDITED CODE:
List<string> newList = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
var table = CreateDataTable();
table.Rows.Add("", "", "");
BindGridView(table);
}
}
//Called on AddRow button click
protected void Add(object sender, EventArgs e)
{
var newTable = PopulateTableFromGridView();
newTable.Rows.Add("", "", "");
BindGridView(newTable);
}
private DataTable PopulateTableFromGridView()
{
var table = CreateDataTable();
for (int i = 0; i < GridView1.Rows.Count; i++)
{
//extract the TextBox values
TextBox box1 = (TextBox)GridView1.Rows[i].FindControl("txt1");
TextBox box2 = (TextBox)GridView1.Rows[i].FindControl("txt2");
TextBox box3 = (TextBox)GridView1.Rows[i].FindControl("txt3");
DropDownList ddl = (DropDownList)GridView1.Rows[i].FindControl("DropDownList1");
table.Rows.Add(box1.Text, box2.Text, box3.Text,ddl.SelectedItem.Text);
}
newList.Add(ddl.SelectedItem.Text);//add selecteditems to a global list
return table;
}
//Sets the first empty row to the grid view
private DataTable CreateDataTable()
{
var dt = new DataTable
{
Columns = { "Column1", "Column2", "Column3","Column4" }
};
return dt;
}
private void BindGridView(DataTable table)
{
GridView1.DataSource = table;
GridView1.DataBind();
for(int i=0;i<GridView1.Rows.Count-1;i++)
{
DropDownList ddl2=(DropDownList)GridView1.Rows[i].FindControl("DropDownList1");
ddl2.ClearSelection();
ddl2.Items.FindByText(newList[i]).Selected = true;
}
}
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
var dt = PopulateTableFromGridView();
if (dt.Rows.Count > 1)
{
dt.Rows[e.RowIndex].Delete();
}
BindGridView(dt);
}
The first screenshot, I have selected NewDelhi from the dropdownlist, which is the 3rd item:
The second screenshot, wherein a new row has been added after AddRow button is clicked, the dropdownlist is realigned in the first row, shows London.
How to make the code persist the dropdownlist selection when AddRow and Delete button is clicked?
I tried disabling the AutoPostBack property of the dropdownlist to false, but to no effect.
Experts please help.
SUCCESSFUL SCREENSHOTS:
I have solved the problem after some R&D.
I have created a new instance of dropdownlist after the gridview is bound, and in that new instance, I am preserving the previous selection using a List from the PopulateGridView method.
Please see the edit of the code.
Hope this helps some body.
Every time you hit the addrow button you are performing a postback.
every postback rebuilds then entire page including the grid based on your table. You can see that in your own code.
But part of this is that the controls within each row are rebuilt too. This includes your DDL's, but you are not saving/restoring the selected values from each drop down. More correctly, the selected values are saved but are invalidated when you recreate the table. you have to handle the RowDatabound event and in each row restore the selected value in the ddl.
But you may have a bigger problem. You are using the same instance of the DDL in each row. this may cause selection/persistence issues. If you find that selecting an item from the ddl causes all rows to have the same selected item, that's the problem in action.
Take a look at the rendered output for your ddl's and make sure the id's are unique for each row.
if the ddl has it's own datasource then you need to create a new instance of a DropDownlist in each row and assign it the same datasource rather than using find control.
if the control has it's list items hard coded then you should just check for unique ddl id's
Related
I have a unique situation. I have added several checkboxes to a gridview and they are populated from a database. They look very good in itemtemplate mode. When I click the Edit button and they are rendered, they loose all settings and appear is unchecked boxes. How do I populate the edititemtemplate checkboxes before they are displayed in edit mode?
Here is the code snippet in the aspx page:
<asp:TemplateField HeaderText="Referral">
<ItemTemplate>
<asp:CheckBox ID="CheckBox7" runat="server" />
</ItemTemplate>
<EditItemTemplate>
<asp:CheckBox ID="CheckBox10" runat="server" />
</EditItemTemplate>
</asp:TemplateField>
and here is the code behind for this checkbox that populates these itemtemplate checkboxes:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//load the referral column from the form3 data column to display the results
TextBox txtReferral = (TextBox)e.Row.FindControl("TextBox82"); //form1
if (txtReferral != null)
{
CheckBox ckbxReferral = (CheckBox)e.Row.FindControl("CheckBox7");
ckbxReferral.Enabled = false;
if (txtReferral.Text.Length > 0)
{
int intReferral = Convert.ToInt32(txtReferral.Text.ToString());
if (intReferral > 0)
{
if (!ckbxReferral.Checked)
{
ckbxReferral.Checked = true;
}
intReferral = 0;
}
}
}
}
I have tried to set the editemtemplate checkboxes, but have had no luck since they are currently null objects. I am a newbie to .net programming, so any help will be greatly appreciated. My ultimate goal is to use the results of the checkboxes to populate two additional child tables from these results.
You need to keep the id of the checkbox controls same in both itemtemplate and edititemtemplate:
<asp:TemplateField HeaderText="Referral">
<ItemTemplate>
<asp:CheckBox ID="CheckBox7" runat="server" />
</ItemTemplate>
<EditItemTemplate>
<asp:CheckBox ID="CheckBox7" runat="server" />
</EditItemTemplate>
</asp:TemplateField>
I have a grid view with a column:
<asp:BoundField DataField="ClosedDate" HeaderText="ClosedDate" SortExpression="ClosedDate" ReadOnly="True" ItemStyle-Width="11%" />
In gridview edit mode when a value is selected in a dropdown then I want to give this ClosedDate cell a value
I have the following code:
protected void ddlState_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow gvr = (GridViewRow)(((Control)sender).NamingContainer);
DropDownList duty = (DropDownList)gvr.FindControl("ddlState");
stateValue = duty.SelectedItem.Value;
if (stateValue == "3")
{
}
}
I only want to update the current edited cell.
I am not sure how to do this.
The row has a few columns but closedDate is empty until state = 3 then give the closedDate cell a date a value or now()
you may use asp:TemplateField with a TextBox instead of asp:BoundField. Then in your DropDownlist_selectedIndexChanged update the value of TextBox
<asp:TemplateField HeaderText="ClosedDate" SortExpression="ClosedDate" ItemStyle-Wrap="false">
<ItemTemplate>
<asp:Label ID="lblCD" runat="server" Text='<%# Eval("ClosedDate") %>'/>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtCD" runat="server" Text='<%# Bind("ClosedDate") %>'/>
</EditItemTemplate>
</asp:TemplateField>
This is a simple gridView I m using in aspx web page
<asp:GridView ID="Order" runat="server" AutoGenerateColumns="False" ShowFooter="True" GridLines="none"
ItemType="MyProject.Models.TempList" SelectMethod="GetList" >
<Columns>
<asp:BoundField DataField="ItemID" HeaderText="ID" SortExpression="ItemID" />
<asp:TemplateField HeaderText="ItemName">
<ItemTemplate>
<asp:Label runat="server" ID="ItemName" Width="40" Visible="true" text="<%#: Item.Item.ItemName %>"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Price(each)">
<ItemTemplate>
<%#: String.Format("{0:c}", Convert.ToDouble(Item.Item.UnitPrice))%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Delete">
<ItemTemplate>
<div style="float:left">
<asp:Button ID="DeleteBtn" runat="server" Text="Delete" OnClick="DeleteBtn_Click"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I have 2+ items in a list<> which is populating the gridView, how can I tell (in the codeBehind.cs) that which Row the "DeleteBtn" was clicked on?
I was using a for loop to iterate every item in gridView using Rows[i] and used a check box to know which item wants to be deleted using a Update button.
But I want to do it directly on a custom created deletebutton.
Thanks in advance, I know I'm missing something silly.
The best way to do that is using CommandName and CommandArgument in your button declaration like that
<asp:Button ID="AddButton" runat="server" CommandName="AddToCart"
CommandArgument="<%# ((GridViewRow) Container).RowIndex %>" Text="Add to Cart" />
you can pass any value in the case we pass the rowIndex, you can get a propertie from your object like that CommandArgument="<%# Eval("id") %>" after that you will handle the onRowCommand method
protected void GridView1_RowCommand(object sender,GridViewCommandEventArgs e)
{
if (e.CommandName == "AddToCart")
{
// Retrieve the row index stored in the
// CommandArgument property.
int index = Convert.ToInt32(e.CommandArgument);
// Retrieve the row that contains the button
// from the Rows collection.
GridViewRow row = GridView1.Rows[index];
// Add code here to add the item to the shopping cart.
}
}
hope it helps :)
Use the button's CommandArgument property; assign Container.DataItemIndex to it. Then use the OnRowCommand event of the gridview and grab the index.
Sample aspx:
<asp:Label runat="server" ID="lblMsg" />
<asp:GridView runat="server" id="gvSample" AutoGenerateColumns="false" OnRowCommand="PerformOperation">
<Columns>
<asp:BoundField DataField="RowValue"/>
<asp:TemplateField>
<ItemTemplate>
<asp:Button Text="Delete" runat="server" CommandName="MyCustomCommand" CommandArgument="<%# Container.DataItemIndex %>" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
PopulateGrid();
}
}
private void PopulateGrid()
{
gvSample.DataSource = Enumerable.Range(0, 10).Select(i => new { RowValue = i });
gvSample.DataBind();
}
protected void PerformOperation(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "MyCustomCommand")
{
var rowIndex = int.Parse(e.CommandArgument);
lblMsg.Text = string.Format("Button on row index: {0} was clicked!", rowIndex);
}
}
Let the button field be given a CommandName, say for example a unique string myCommandName in the Edit columns dialog box. Don't worry about the CommandArgument. Then, in the Grid view Row command event, you can check which button (i.e. column) is clicked by tracing the command name like if e.commandname = "mycommandname", at the same time the CommandArgument will also be available as String and all we have to do is to converttoint32, something like intSelectedRow = convert.ToInt32(e.CommandArgument) which will give us the selected row's index.
I want to show data in dropdown list from database at the time of i edit row. Drop down list is placed in <EditItemTemplate> how to access this dropdown list in code file..
<asp:TemplateField ItemStyle-Width="30px" HeaderText="Group of Broker">
<itemtemplate>
<asp:Label ID="lblGroupofBroker" runat="server" Text='<%# Eval("groupofbroker")%>'></asp:Label>
</itemtemplate>
<edititemtemplate>
<asp:DropDownList ID="ddlGroupofBroker" runat="server" DataTextField='<%# Eval("groupofbroker") %>'> </asp:DropDownList>
</edititemtemplate>
<itemstyle width="30px" />
<footertemplate>
<asp:DropDownList ID="DropDownList1" runat="server"></asp:DropDownList>`
</footertemplate>
</asp:TemplateField>
Plese Help ME how to access this drop down list in code file to fill data from database
you need to handle gridview_RowEditing event
protected void gridview_RowEditing(object sender, GridViewEditEventArgs e)
{
GridViewRow row = gvAllClients.Rows[e.NewEditIndex];
// Change the row state
DropDownList ddlDataType = (DropDownList)(row.FindControl("ddlDataTypeAll"));
//ddlDataType.DataSource = <datasocurce>;
//ddlDataType.DataBind();
}
Hi I have a grid view with a textbox in each row that im trying to get the value of in the RowCommand event. The below code works fine for all rows expect the first one. The textbox.text value for the first row in always empty.
<asp:GridView ID="GridView1" runat="server" OnRowCommand="GridView1_OnRowCommand" >
<Columns>
<asp:TemplateField>
<ItemTemplate>
Title <%# Eval("Title")%>
<asp:TextBox ID="TextBoxAddPost" runat="server"></asp:TextBox>
<asp:LinkButton ID="LinkButtonAddPost" CommandName="AddPost" CommandArgument='<%# Eval("postId") %>' runat="server">Add Post</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code-behind:
protected void Page_Load(object sender, EventArgs e)
{
if(IsPostBack)
bindGridView();
}
protected void GridView1_OnRowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "AddPost")
{
GridViewRow row = (GridViewRow)(((LinkButton)e.CommandSource).NamingContainer);
TextBox textBox = (TextBox)row.FindControl("TextBoxAddPost");
//Empty for first row but works for all others
Debug.WriteLine("row: " + row.RowIndex + ", textBox:" + textBox.Text.Trim());
GridView1.DataBind();
}
}
The above code has been simplified for illustration purposes. Each row actually contains a child gridview, hence why in need the text box in each row. I fear that the binding in the page_load is overwriting the value of the text box, however, without the page_load binding, the rowCommand Event is not fired.
I find i a bit strange the it works fine for all rows except the first.
For getting data from textbox, You have to set text property first by putting below code.
<asp:TextBox ID="TextBoxAddPost" runat="server" Text='<%# Eval("Title") %>'></asp:TextBox>
It will definitely give value from textbox.
Either way, You can also set datakeynames property of gridview.Click here for datakeynames
I tried this and it works fine,GridView1_OnRowCommand fires by clicking on LinkButtonAddPost:
<asp:GridView ID="GridView1" runat="server" OnRowCommand="GridView1_RowCommand">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="TextBoxAddPost" runat="server" Text='<%# Eval("ID") %>'></asp:TextBox>
<asp:LinkButton ID="LinkButtonAddPost" CommandName="AddPost" CommandArgument='<%# Eval("ID") %>' runat="server">Add Post</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
and change your page_load event like this:
protected void Page_Load(object sender, EventArgs e)
{
GridView1.DataSource = Data.RequestPaymentDB.GetRequestPaymentByRequestID(9208060001);
GridView1.DataBind();
}
compare your code with mine.