I have a gridview that is populated with data from SQL and I would like to add buttons/linkbuttons dynamically to its columns.
protected void gridview_RowDataBound(object sender, GridViewRowEventArgs e)
{
Button button = new Button();
button.ID = "row" + e.Row.RowIndex;
button.Text = "click me";
button.Click += new EventHandler(Unnamed_Click);
e.Row.Cells[1].Controls.Add(button);
}
Visually that works fine but when clicking it, it does a postback and the changes are lost. The buttons are gone.
Where can I recreate them so they persist?
You can use command field or template field for buttons,
below is example for image button:
<asp:CommandField ShowEditButton="true" EditImageUrl="~/images/edit.png" ButtonType="Image" ItemStyle-Width="20px" HeaderStyle-Width="20px" AccessibleHeaderText="Edit">
<HeaderStyle Width="20px" />
<ItemStyle Width="20px" />
</asp:CommandField>
Or
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="btnEdit" runat="server" CommandName="Edit"
ImageUrl="~/images/edit.png" ToolTip="Click to Edit></asp:ImageButton>
</ItemTemplate>
</asp:TemplateField>
Please use the below steps to bypass the binding of grid in case the click me button was clicked
Change your OnRowBound function code to:
protected void gridview_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.DataItemIndex != -1)
{
Button button = new Button();
button.ID = "gridview1row" + e.Row.RowIndex;
button.UseSubmitBehavior = false;
button.Text = "click me";
button.Click += new EventHandler(Unnamed_Click);
e.Row.Cells[1].Controls.Add(button);
}
}
Add the below check to you Page_Load before Grid View Load
protected void Page_Load(object sender, EventArgs e)
{
try
{
if ( Request.Params["__EventTarget"] == null || !Request.Params["__EventTarget"].Contains("gridview1row"))
{
using (SqlConnection connection = new SqlConnection(GetConnectionString()))
{
using (SqlCommand command =
new SqlCommand("SELECT TOP 100 * FROM dbo.TableName", connection))
{
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = command;
da.Fill(ds);
GridView1.DataSource = ds;
GridView1.DataBind();
}
}
}
}
catch (Exception ex)
{
}
}
Related
I have a DataList and bind it corrertly.
SqlCommand cmd = new SqlCommand(str_cmd, conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
dtlst_periodicTask.DataSource = ds;
dtlst_periodicTask.DataBind();
pds.DataSource = ds.Tables[0].DefaultView;
pds.AllowPaging = true;
pds.PageSize = 25;
pds.CurrentPageIndex = CurrentPage;
lnkbtnNext.Enabled = !pds.IsLastPage;
lnkbtnPrevious.Enabled = !pds.IsFirstPage;
and some codes for paging.
After that, I need to add a number of Buttons in each row dynamically because the number of buttons is not fix.
foreach (DataListItem item in dtlst.Items)
{
Button btn = new Button();
btn.Click += new EventHandler(btn_Click);
pnl_users.Controls.Add(btn);
}
But the button click event does not work.
protected void btn_Click(object sender, EventArgs e)
{
// code does not fire.
}
When I put a Button in .aspx page, have access and it works.
protected void dtlst object source, DataListCommandEventArgs e)
{
}
but why are you attempting to inject a button?
Why not just include the button in the markup in the first place? I can't really see the need or reason to layout a datalist, and THEN decide to use code?
Just drag + drop in a button into the datalist, and you are quite much done.
So here is our datalist - we dropped in a plane jane button.
<asp:DataList ID="DataList1" runat="server" DataKeyField="ID" >
<ItemTemplate>
<div style="border-style:solid;color:black;width:300px;margin-left:25px">
<div id="mybox" runat="server" style="padding:5px;text-align:right">
<p>Hotel Name: <asp:TextBox ID="HotelName" runat="server" Text ='<%# Eval("HotelName") %>' /></p>
<p>First Name: <asp:TextBox ID="FirstName" runat="server" Text ='<%# Eval("FirstName") %>' /></p>
<p>Last Name: <asp:TextBox ID="LastName" runat="server" Text ='<%# Eval("LastName") %>' /></p>
<p>City: <asp:TextBox ID="City" runat="server" Text ='<%# Eval("City") %>' /></p>
<p>Province: <asp:TextBox ID="Province" runat="server" Text ='<%# Eval("Province") %>' /></p>
Active: <asp:CheckBox ID="Active" runat="server" Checked = '<%# Eval("Active") %>'/>
<br />
<asp:Button ID="cmdRow" runat="server" Text="Row click This item"
/>
</div>
</div>
<div style="height:15px"></div>
</ItemTemplate>
</asp:DataList>
And our code to fill looks like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
MyLoadData();
}
void MyLoadData()
{
using (SqlConnection con = new SqlConnection(Properties.Settings.Default.TEST4))
{
string strSQL = "SELECT TOP 3 * FROM tblHotels ORDER BY HotelName";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, con))
{
con.Open();
DataList1.DataSource = cmdSQL.ExecuteReader();
DataList1.DataBind();
}
}
And we now have this:
Now, lets wire up the button click, like this:
so, create new event in above (inteli-sense offers this choice).
protected void cmdRow_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
DataListItem gRow = (DataListItem)btn.Parent;
Debug.Print("Row index = " + gRow.ItemIndex.ToString());
int pkID = (int)(DataList1.DataKeys[gRow.ItemIndex]);
Debug.Print("Data base PK id = " + pkID.ToString());
Debug.Print("Hotel name = " + ((TextBox)(gRow.FindControl("HotelName"))).Text);
Debug.Print("City = " + ((TextBox)(gRow.FindControl("City"))).Text);
Debug.Print("--------------------");
}
And out output is this:
Row index = 1
Data base PK id = 72
Hotel name = Banff Rocky Mountain Resort
City = Banff
--------------------
so, it not at all clear why you want to spend the time, effort, and that of writing code when you can as a general rule just drop in a good old plane jane button from the designer right into the datalist, and then simple wire up a event.
Edit:
You can lead a horse to water - but can you get the horse to drink the water?
You can as noted inject a button, but I REALLY but REALLY but REALLY do not recommend doing this.
However, to get the button click event to work, then you can do this:
HtmlButton btn = new HtmlButton();
btn.InnerText = "Index " + e.Item.ItemIndex;
btn.Attributes.Add("onclick","__doPostBack('BtnTest2','')");
btn.ViewStateMode = ViewStateMode.Enabled;
HtmlGenericControl MyDiv = (HtmlGenericControl)e.Item.FindControl("mybox");
MyDiv.Controls.Add(btn);
Edit2:
Ok, there seems to be a issue of persistence.
So, adding MUST occur on page load (or could be earlier).
And the buttons have to be re-inserted each time on post-backs.
This now works:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
MyLoadData();
}
AddBtns();
}
void MyLoadData()
{
using (SqlConnection con = new SqlConnection(Properties.Settings.Default.TEST4))
{
string strSQL = "SELECT TOP 3 * FROM tblHotels ORDER BY HotelName";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, con))
{
con.Open();
DataList1.DataSource = cmdSQL.ExecuteReader();
DataList1.DataBind();
}
}
}
void AddBtns()
{
foreach (DataListItem gRow in DataList1.Items)
{
Button btn = new Button();
btn.Text = "Index " + gRow.ItemIndex;
btn.ID = "Btn" + gRow.ItemIndex;
btn.Click += new EventHandler(BtnTest3);
HtmlGenericControl MyDiv = (HtmlGenericControl)gRow.FindControl("mybox");
MyDiv.Controls.Add(btn);
}
}
void BtnTest3(object sender, EventArgs e)
{
Debug.Print("buttn3 click");
}
Note two changes:
We don't add/inject the buttons ONLY on !IsPostback.
We inject the buttons each time on page load
We did not use the Item bound event.
So basically i want to create a booking and a booking can have multiple orders but i dont know how to store the orders that have been selected in the other pages etc. but I already know i have to do a cycle to run the gridview bue i dont know how to do that with a pager and with a search textbox.
this is how it looks:
Current CS
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Configuration;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Gestão_de_embarques
{
public partial class CriarEcomenda : System.Web.UI.Page
{
SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["constring"].ConnectionString);
protected void Page_Load(object sender, EventArgs e)
{
con.Open();
string user = Convert.ToString(Session["user"]);
username.Text = user;
if (Session["user"] == null || Session["login"] == null)
{
Response.Redirect("Login.aspx", false);
}
if (!Page.IsPostBack)
{
refreshdata();
}
con.Close();
}
public void refreshdata()
{
SqlCommand cmd = new SqlCommand("select DISTINCT No_ from [Encomenda]", con);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
sda.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
}
protected void btnsearch_Click(object sender, EventArgs e)
{
con.Open();
if (txtSearch.Value == "")
{
refreshdata();
}
else
{
try
{
SqlCommand cmd = new SqlCommand("select DISTINCT No_ from [encomenda] where No_= #No_", con);
cmd.Parameters.Add("#No_", SqlDbType.NVarChar).Value = txtSearch.Value;
SqlDataReader sdr = cmd.ExecuteReader();
if (sdr.Read())
{
sdr.Close();
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
sda.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
con.Close();
}
else
{
SqlDataAdapter sda = new SqlDataAdapter(cmd);
sdr.Close();
DataTable dt = new DataTable();
sda.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
ButtonCreate.Visible = false;
}
}
catch(Exception ex)
{
}
}
}
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
refreshdata();
}
}
}
Well, if you were not data paging, then the un-bound check box would persist and survive even post backs.
But, since you have data paging? Then you persist the selected PK id from the database. (you don't have to display the pk row, but just set DataKeys = "ID" or what ever your PK row is from the database.
As noted, with searching and paging, you have to re-bind the grid, so you can't use the grid to persist the selected check boxes. Say we have a list of hotels to select.
Our markup would be this:
<div style="width:40%">
<asp:GridView ID="MyGrid" runat="server" CssClass="table table-hover"
DataKeyNames="ID" AutoGenerateColumns="false" OnRowDataBound="MyGrid_RowDataBound" >
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" />
<asp:BoundField DataField="HotelName" HeaderText="Hotel Name" />
<asp:BoundField DataField="HotelName" HeaderText="Hotel Name" />
<asp:BoundField DataField="Province" HeaderText="Province" />
<asp:TemplateField HeaderText="Select">
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server" OnCheckedChanged="CheckBox1_CheckedChanged" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Button ID="Button1" runat="server" Text="Show Selected rows" OnClick="Button1_Click" />
<br />
<br />
</div>
And code to load up this grid would be:
List<int> MySelected = new List<int>();
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
LoadGrid();
ViewState["MySelected"] = MySelected;
}
else
{
MySelected = (List<int>)ViewState["MySelected"];
}
}
public void LoadGrid()
{
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from tblHotels ORDER BY HotelName",
new SqlConnection(Properties.Settings.Default.TEST3)))
{
cmdSQL.Connection.Open();
DataTable rst = new DataTable();
rst.Load(cmdSQL.ExecuteReader());
MyGrid.DataSource = rst;
MyGrid.DataBind();
}
}
protected void MyGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int PkRow = (int)((DataRowView)e.Row.DataItem)["ID"];
CheckBox ckbox = (CheckBox)e.Row.FindControl("CheckBox1");
if (MySelected.Contains(PkRow)) {
ckbox.Checked = true;
}
}
}
protected void CheckBox1_CheckedChanged(object sender, EventArgs e)
{
CheckBox ckBox = (CheckBox)sender;
GridViewRow gvRow = (GridViewRow)ckBox.Parent.Parent;
int RowPK = (int)(MyGrid.DataKeys[gvRow.RowIndex]["ID"]);
if (ckBox.Checked)
MySelected.Add(RowPK);
else
MySelected.Remove(RowPK);
}
Now how I just created a simple list. When you check a box, you simply add the PK row from the GridRow "PK" to the list.
The code to get/work the "list" from the database thus will look like this:
protected void Button1_Click(object sender, EventArgs e)
{
string MyPkList = string.Join(",", MySelected);
string strSQL = "SELECT * from tblHotels where ID IN(" + MyPkList + ")";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, new SqlConnection(Properties.Settings.Default.TEST3)))
{
cmdSQL.Connection.Open();
DataTable rstPickList = new DataTable();
rstPickList.Load(cmdSQL.ExecuteReader());
foreach (DataRow OneRow in rstPickList.Rows)
{
Response.Write("<h2> PK = " + OneRow["Id"].ToString() + " Hotel Name = " + OneRow["HotelName"] + "</h2>");
}
}
}
So, if I check say 3 rows, and hit that button, you get this:
this does mean that you have to set the check box to auto post back. And that thus means for a check box click, you do post-back. However, you could drop the whole grid in a update panel if you need to only post back that grid selecting part and not the whole page.
Once you have that list of PK values from the database, then as the button shows, we have to process against the database table, and we can't use the grid due to paging. As noted, if the gridview could fit on one page, then you would not need the persisting code, and you could just loop the grid view to get the checked rows - you would not need ANY code to persist the values.
I am trying to figure it out how can I display a dropDownList on a specific cell in the table right after clicking a button "Show DropDownlist" located on that cell.
This is the behind code , right now it is displaying the dropDownList at the last cell of each row. and I want to make it appear only when a button is clicked.
while (rdr.Read())
{
TableRow tRow = new TableRow();
myTable.Rows.Add(tRow);
for (int i = 0; i <= 4; i++)
{
// Create a new cell and add it to the row.
TableCell tCell = new TableCell();
if (i == 4)
{
tCell.Controls.Add(SM_List()); //Adding the dropdownlist
tRow.Cells.Add(tCell);
continue;
}
tCell.Text = rdr.GetString(i);
tCell.Attributes.Add("onmouseover", "this.style.cursor = 'pointer'; this.style.backgroundImage = ''; ");
tCell.Attributes.Add("onClick", "getData()");
tRow.Cells.Add(tCell);
}
/* iterate once per row */
}
I want to add this code, so it will be a button at first , instead of a drop down list :
Button bt = new Button();
bt.Text = "Switch";
bt.Click += new EventHandler(DropDownList_Show);
tCell.Controls.Add(bt);
But I am not sure how to display the DropDownList at the exact cell the button was located. and also I want to do some actions when Value was selected in the dropdownlist.
Can you please assist , I feel a little bit lost.
You can solve this issue easily by using GridView in ASP.NET.
Let say the GridView is declared as following in ASPX page.
<asp:GridView ID="GridView1" runat="server" OnRowCommand="GridView1_RowCommand" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="Id" />
<asp:BoundField DataField="Token" />
<asp:BoundField DataField="Secret" />
<asp:ButtonField CommandName="ShowDropDown" Text="Show" />
<asp:TemplateField>
<ItemTemplate>
<asp:DropDownList ID="dropDownList" runat="server" Visible="false">
<asp:ListItem Text="Valid" Value ="1"></asp:ListItem>
<asp:ListItem Text="Invalie" Value ="2"></asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Following is the method in code behind which populates the GridView.
private void BindGridView()
{
var tokens = new List<AccessToken>();
using (var conn = new SqlConnection("Server=somedbserver;Database=somedatabase;User Id=someuser;Password=somepassword;"))
{
using (var command = new SqlCommand())
{
command.Connection = conn;
command.CommandText = "SELECT Id, Token, Secret FROM Tokens";
command.CommandType = System.Data.CommandType.Text;
conn.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
var token = new AccessToken();
token.Id = reader.GetInt32(0);
token.Token = reader.GetString(1);
token.Secret = reader.GetString(2);
tokens.Add(token);
}
}
}
}
GridView1.DataSource = tokens;
GridView1.DataBind();
}
And I am calling this method in Page_Load.
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
BindGridView();
}
}
Following is the event handler of RowCommand event of GridView which will display the dropdown list in the column next to the button which is clicked.
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if(e.CommandName == "ShowDropDown")
{
var row = GridView1.Rows[Convert.ToInt32(e.CommandArgument)];
//Using Cell[4] coz the Dropdownlist is in 5th column of the row.
//You need to replace 4 with appropriate column index here.
//Also replace "dropDownList" with the ID assigned to the dropdown list in ASPX.
var ddl = (DropDownList)row.Cells[4].FindControl("dropDownList");
if(ddl != null)
{
ddl.Visible = true;
}
}
}
You will able resolve your issue if you follow this approach.
When click on delete link-button in gridview, Confirmation Box not appeared. I write this code but I don't know why it's not working...
<asp:GridView ID="gvwAuctionExport" runat="server" AutoGenerateColumns="false" OnRowCommand="gvwAuctionExport_RowCommand" OnRowDataBound="gvwAuctionExport_RowDataBound" OnRowDeleting="gvwAuctionExport_RowDeleting">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<div class="btn-group btn-group-xs" id="bgroup">
<asp:LinkButton ID="lnkInspectionDelete" runat="server" Text="Delete" CssClass="btn btn-danger" CommandArgument='<%# Eval("inspection_id") %>' CommandName="Delete"></asp:LinkButton>
</div>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="address" HeaderText="Address" />
<asp:BoundField DataField="city" HeaderText="City" />
<asp:BoundField DataField="state" HeaderText="State" />
</Columns>
</asp:GridView>
protected void gvwAuctionExport_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
int InspectionID = Convert.ToInt32(e.CommandArgument);
string status = string.Empty;
status = DACls.DeleteInspectionByID(InspectionID);
}
}
protected void gvwAuctionExport_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
LinkButton l = (LinkButton)e.Row.FindControl("lnkInspectionDelete");
l.Attributes.Add("onclick", "javascript:return " +
"confirm('Are you sure you want to delete this record");
}
}
protected void gvwAuctionExport_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
bindGridView();
}
public void bindGridView(){
DataSet DS = new DataSet();
SqlConnection DBCon = new SqlConnection(ConfigurationManager.ConnectionStrings["ConStr"].ConnectionString);
SqlCommand Cmd = new SqlCommand("USP_Inspection_Export", DBCon);
Cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter AHadp = new SqlDataAdapter(Cmd);
AHadp.Fill(this.DS);
DataTable dt = DS.Tables[0];
this.gvwAuctionExport.DataSource = dt;
this.gvwAuctionExport.DataBind();
}
When I click on delete button and check from debugger it is not going to GridView RowDataBound function scope. I don't know what happening here?
I'm having trouble with setting a HiddenField's value to a GridView item value. What I want to do is get the value of a BoundField (in this case, "FIPSCountyCode") in a GridView and store it in a HiddenField when the user clicks a button (in this case, "btnEdit") to make changes to a entry in the grid. I haven't used HiddenFields before, so I have forgotten what to do here.
The HiddenField is setup like this:
<asp:HiddenField ID="hdnFIPS" Value='<%#Eval("FIPSCountyCode")%>' runat="server" />
This is what the GridView is setup like:
<asp:GridView ID="CountyList" runat="server" AutoGenerateColumns="False" Width="90%" SkinId="PagedList" PagerSettings-Position="TopAndBottom" PagerStyle-Wrap="True">
<Columns>
<asp:BoundField HeaderText="County Code" DataField="FIPSCountyCode" />
<asp:BoundField HeaderText="State Code" DataField="StateCode" />
<asp:BoundField HeaderText="County Name" DataField="CountyName" />
<asp:BoundField HeaderText="Tax Rate" DataField="TaxRate" />
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="btnEdit" runat="server" SkinID="EditIcon" OnClick="EditInfo" CommandName="DoEdit" />
<asp:ImageButton ID="DeleteButton" runat="server" SkinID="DeleteIcon" CommandName="DoDelete"
OnClientClick="return confirm('Are you sure you want to remove this item and all of its options?')"
CausesValidation="false" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<AlternatingRowStyle CssClass="even" />
</asp:GridView>
And this is the code behind:
public partial class Admin_County_Info : CommerceBuilder.UI.AbleCommerceAdminPage
{
private string redirectString = String.Empty;
protected void Page_Load(object sender, System.EventArgs e)
{
if (!Page.IsPostBack)
PopulateCountyGrid();
}
protected void PopulateCountyGrid()
{
try
{
System.Data.SqlClient.SqlDataReader dr = null;
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["AbleCommerce"].ToString()))
{
SqlCommand cmd = new SqlCommand("SELECT [FIPSCountyCode], [StateCode], [CountyName], [TaxRate] FROM [baird_InfoCounty]", cn);
cmd.CommandType = CommandType.Text;
cn.Open();
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
CountyList.DataSource = dr;
CountyList.DataBind();
}
}
catch (Exception eX)
{
}
}
#region Clicks and Event Handlers
protected void EditInfo(object sender, System.EventArgs e)
{
if (Page.IsValid)
{
redirectString = "~/Admin/Taxes/AddEditCountyInfo.aspx?FIPSCountyCode=" + hdnFIPS.Value;
Response.Redirect(redirectString);
}
}
protected void AddInfo(object sender, System.EventArgs e)
{
if (Page.IsValid)
{
Response.Redirect("~/Admin/Taxes/AddEditCountyInfo.aspx");
}
}
}
This must be a really dumb question but I'm really not sure how to proceed. Any help would be great!
You can get the value of FIPSCountyCode from the BoundField this way:
protected void EditInfo(object sender, System.EventArgs e)
{
if (Page.IsValid)
{
GridViewRow gvr = ((ImageButton)sender).NamingContainer as GridViewRow;
hdnFIPS.Value = gvr.Cells[0].Text;
redirectString = "~/Admin/Taxes/AddEditCountyInfo.aspx?FIPSCountyCode=" + hdnFIPS.Value;
Response.Redirect(redirectString);
}
}