I created a gridview dynamically and added the AutoGenerateEditButton = true; property and i see that it adds the edit link to all the fields when it loads the table into the gridview. But when i click the edit button nothing happens, except for a postback. What am i doing wrong?
GridView gridData = new GridView();
gridData.ID = "test";
gridData.AutoGenerateEditButton = true;
gridData.RowEditing += (sender, e) => grid_RowEditing(tbl, e, sender);
gridData.DataSource = tbl;
gridData.DataBind();
protected void grid_RowEditing(DataTable tbl, GridViewEditEventArgs e, object sender)
{
((GridView)sender).EditIndex = e.NewEditIndex;
// call your databinding method here
((GridView)sender).DataSource = tbl ;
((GridView)sender).DataBind();
}
My guess is that because you are overwriting the grid with every postback by recreating it, the click is just ignored.
The suggested approach would be to create the invisible grid statically:
<asp:GridView .... Visible="false" />
and then just make it visible when needed. This approach (in contrast to dynamic creation) will save you from dozen of issues, most probably including the one you face.
Edit: if you really, really want to follow your route then my guess is that you just haven't specified your data key names so that the edit click carries no information on the clicked row.
gridData.DataKeyNames = new string[] { "ID" };
(if your primary key column name is ID)
I added a <p id="p" runat="server"> on client side and added that grid inside this control.
Here is my code.
I used SqlDataSource instead of Datatable, you can use it any one of it.
Hope it works for u..
protected void gridview()
{
GridView gridData = new GridView();
gridData.ID = "test";
gridData.AutoGenerateEditButton = true;
gridData.RowEditing += (sender, e) => grid_RowEditing(SqlDataSource1, e, sender);
gridData.DataSource = SqlDataSource1;
gridData.DataBind();
p.Controls.Add(gridData);
}
protected void grid_RowEditing(SqlDataSource tbl, GridViewEditEventArgs e, object sender)
{
((GridView)sender).EditIndex = e.NewEditIndex;
// call your databinding method here
((GridView)sender).DataSource = tbl;
((GridView)sender).DataBind();
}
2) I tried with datatable too, and its working.
here is my code.
protected void gridview()
{
DataTable dt = new DataTable();
dt.Columns.Add("id");
dt.Columns.Add("name");
for (int i = 0; i < 100; i++)
{
dt.Rows.Add(i.ToString(),"v"+i.ToString());
}
GridView gridData = new GridView();
gridData.ID = "test";
gridData.AutoGenerateEditButton = true;
gridData.RowEditing += (sender, e) => grid_RowEditing(dt, e, sender);
gridData.DataSource = dt;
gridData.DataBind();
p.Controls.Add(gridData);
}
protected void grid_RowEditing(DataTable tbl, GridViewEditEventArgs e, object sender)
{
((GridView)sender).EditIndex = e.NewEditIndex;
// call your databinding method here
((GridView)sender).DataSource = tbl;
((GridView)sender).DataBind();
}
Related
I am trying to add the column names of a gridview to a dropdown list.
The problem is when I change the datasource of the gridview, it returns empty.
I am not sure whether the event is working properly, as it does not work with/without it.
I wanted to use the DataBindComplete event, but I could not see it so I tried DataBound instead.
private void BindTable()
{
if (ddTableSearch.SelectedIndex == 0)
{
tblCustomerTableAdapter customerAdapter = new tblCustomerTableAdapter();
GridView2.DataSource = customerAdapter.GetData();
GridView2.DataBind();
}
else if (ddTableSearch.SelectedIndex == 1)
{
tblInvoiceTableAdapter invoiceAdapter = new tblInvoiceTableAdapter();
GridView2.DataSource = invoiceAdapter.GetData();
GridView2.DataBind();
}
else if (ddTableSearch.SelectedIndex == 2)
{
tblEstimateTableAdapter estimateAdapter = new tblEstimateTableAdapter();
GridView2.DataSource = estimateAdapter.GetData();
GridView2.DataBind();
}
}
protected void GridView2_DataBound(object sender, EventArgs e)
{
// Populate dropdown with column names
ddColumnSearch.Items.Clear();
for (int i = 0; i < GridView2.Columns.Count; i++)
{
ddColumnSearch.Items.Add(new ListItem(GridView2.Columns[i].ToString()));
}
}
What am I doing wrong?
The databound event runs for each record in the gridview. So one issue is that each time you are clearing out the items you added before. Another issue is that you need to get the data from the EventArgs instead of from the gridview.columns since those are not there until after all the data is bound. I think all you need to do is get the data from the header row:
protected void GridView2_DataBound(object sender, EventArgs e)
{
// Populate dropdown with column names
if(e.Row.RowType != DataControlRowType.Header) return; //only continue if this is hdr row
ddColumnSearch.Items.Clear();
foreach (TableCell cell in e.Row.Cells)
{
ddColumnSearch.Items.Add(new ListItem(cell.Text));
}
}
I have a dropdown which is bound to a database. On its index change there is a function that add some button in a panel based upon selected value.
I am reading those button in page_init event but still I get null values, i.e. event bound with the button never fires.
Here is my code and dropdownlist1 is the dropdown that is adding dynamic button.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
colorgroupsTableAdapters.master_color_groupTableAdapter ta
= new colorgroupsTableAdapters.master_color_groupTableAdapter();
DataTable dt = ta.GetData();
DropDownList1.DataSource = dt;
DropDownList1.DataTextField = dt.Columns[1].ToString();
DropDownList1.DataValueField = dt.Columns[0].ToString();
DropDownList1.DataBind();
DropDownList1.Items.Insert(0, new ListItem("Select One", "0"));
}
}
protected void Page_Init(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
bindcolors();
}
}
protected void DropDownList1_DataBound(object sender, EventArgs e)
{
}
protected void DropDownList2_DataBound(object sender, EventArgs e)
{
if (DropDownList1.SelectedIndex < 1)
{
DropDownList2.Items.Clear();
}
DropDownList2.Items.Insert(0, new ListItem("Select One", "0"));
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
ViewState["dd"] = DropDownList1.SelectedIndex;
bindcolors();
}
void bindcolors()
{
if (DropDownList1.SelectedIndex > 0)
{
addcolorgroupsTableAdapters.groupavailablecolorTableAdapter ta
= new addcolorgroupsTableAdapters.groupavailablecolorTableAdapter();
DataTable dt = ta.GetData(int.Parse(DropDownList1.SelectedValue));
HtmlTable ht = new HtmlTable();
ht.Width = "90%";
ht.Border = 1;
for (int i = 0; i < dt.Rows.Count; i++)
{
HtmlTableRow tr = new HtmlTableRow();
HtmlTableCell tc1 = new HtmlTableCell();
HtmlTableCell tc2 = new HtmlTableCell();
HtmlTableCell tc3 = new HtmlTableCell();
object[] ob = dt.Rows[i].ItemArray;
tc1.InnerHtml = ob[0].ToString();
tc2.InnerHtml = ob[1].ToString();
tc2.BgColor = "#" + ob[1].ToString();
Button b = new Button();
b.Text = "Remove";
b.CommandArgument = ob[0].ToString();
AjaxControlToolkit.ConfirmButtonExtender cb
= new AjaxControlToolkit.ConfirmButtonExtender();
cb.ConfirmText = "Are You Sure To Delete This Color From The Group?";
b.ID = "Bo" + ob[0].ToString();
b.EnableViewState = true;
b.Click += new EventHandler(b_Click);
cb.TargetControlID = "Bo" + ob[0].ToString();
tc3.Controls.Add(b);
tc3.Controls.Add(cb);
tr.Cells.Add(tc1);
tr.Cells.Add(tc2);
tr.Cells.Add(tc3);
ht.Rows.Add(tr);
}
Panel1.Controls.Add(ht);
}
}
void b_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
int grp = int.Parse(DropDownList1.SelectedValue);
int clid = int.Parse(b.CommandArgument);
addcolorgroupsTableAdapters.QueriesTableAdapter ta
= new addcolorgroupsTableAdapters.QueriesTableAdapter();
ta.DeleteQuery_group_color(grp, clid);
DropDownList2.DataBind();
bindcolors();
}
protected void Button1_Click(object sender, EventArgs e)
{
if (DropDownList1.SelectedIndex > 0 && DropDownList2.SelectedIndex > 0)
{
int grp = int.Parse(DropDownList1.SelectedValue);
int clid = int.Parse(DropDownList2.SelectedValue);
addcolorgroupsTableAdapters.QueriesTableAdapter ta
= new addcolorgroupsTableAdapters.QueriesTableAdapter();
ta.Insert_into_group_color(grp, clid);
DropDownList2.DataBind();
bindcolors();
}
}
Please tell what I am doing wrong?
I think the problem is the check for SelectedIndex > 0 in bindControls. The reason is that ViewState is evaluated between the Init and Load so the value for the SelectedIndex property is not set yet (and therefore = -1).
You could try a different approach: use a Repeater control that is databound to the results of the database query. This way, the general structure can be defined in the Repeater and its ItemTemplate. Also the EventHandlers are registered in the ItemTemplate.
You can reset the DataSource of the Repeater whenever the SelectedIndex of the Combobox changes and do not need to recreate the controls dynamically in init.
Your code should be much shorter and behave more deterministic.
I'm using AJAX Control Toolkit to create Tabpanels. Each panel is populated with a gridview as per below code.
Now, I want to add one button per each row. When it is clicked it should pass as parameter one of the cells of that row, but as the Gridview is dynamically created, I don't know how. Any tips?
foreach (DataTable dt in DataSet1.Tables)
{
GridView gv = new GridView();
var thepanel = new AjaxControlToolkit.TabPanel();
gv.DataSource = dt;
gv.DataBind();
thepanel.Controls.Add(gv);
TabContainer.Controls.Add(thepanel);
}
You can add a select button to your grid as follows:
Gridview1.AutoGenerateSelectButton=true;
I just found a solution for whom this may interest:
First, you should include fllwg lines BEFOREthe databind:
gv.RowDataBound += gv_RowDataBound;
gv.RowCommand += gv_RowCommand;
Then define the RowDataBound to insert the Linkbutton:
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
LinkButton butIgnorar = new LinkButton()
{
CommandName = "Ignorar",
ID = "butIgnorar",
Text = "Ignorar",
//optional: passes contents of cell 1 as parameter
CommandArgument = e.Row.Cells[1].Text.ToString()
};
//Optional: to include some javascript cofirmation on the action
butIgnorar.Attributes.Add("onClick", "javascript:return confirm('Are you sure you want to ignore?');");
TableCell tc = new TableCell();
tc.Controls.Add(butIgnorar);
e.Row.Cells.Add(tc);
}
}
Finally, you call the command from the RowCommand
protected void gv_RowCommand(object sender, GridViewCommandEventArgs e)
{
string currentCommand = e.CommandName;
string parameter= e.CommandArgument.ToString();
if (currentCommand.Equals("Ignorar"))
{
yourMethodName(parameter);
}
}
Hope that this is helpful for somebody!
I created a grid view application and outside of my template I have a Add new row button. When i add a new row , it gets placed with an Edit and delete button. What I'm trying to do is when I click the add new row button, i want it to open the new row in editing mode, so no blank rows can be added with empty information. So basically if I add a new row and dont input information it wont be created.
If I need to be more thorough on my explanation please ask.
Any help will be appreciated.
Thank you
I ended up figuring out the problem on my own. It works perfect now. I as well changedup the database but I'm providing my code. Im sure there is an easier way but this was the best I could do: If you guys can provide inputs on an easier way I would appreciate it.
protected void gv_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Insert") //- this is needed to explain that the INSERT command will only work when INSERT is clicked
{
gv.DataBind();
DataTable d = dbcon.GetDataTable("SELECT * FROM CIS.CIS_TRANS ORDER BY ID DESC", "ProjectCISConnectionString");
string transCode = "", fundCode = "", BSA_CD = "", DP_TYPE = "";
if (d.Rows.Count > 0)
{
transCode = d.Rows[0]["TRANS_CD"].ToString();
fundCode = d.Rows[0]["FUND_CD"].ToString();
BSA_CD = d.Rows[0]["BSA_CD"].ToString();
DP_TYPE = d.Rows[0]["DP_TYPE"].ToString();
if (transCode.Trim().Length > 0)
{
dbcon.Execute("INSERT INTO CIS.CIS_TRANS (TRANS_CD) VALUES('')", "ProjectCISConnectionString");
gv.DataBind();
}
}
gv.EditIndex = gv.Rows.Count - 1;
}
else if (e.CommandName == "Cancel")
{
DataTable d = dbcon.GetDataTable("SELECT * FROM CIS.CIS_TRANS ORDER BY ID DESC", "ProjectCISConnectionString");
string transCode = "";
if (d.Rows.Count > 0)
{
transCode = d.Rows[0]["TRANS_CD"].ToString();
if (transCode.Trim().Length == 0)
{
dbcon.Execute(string.Format("DELETE CIS.CIS_TRANS WHERE ID = '{0}'", d.Rows[0]["ID"]), "ProjectCISConnectionString");
gv.DataBind();
}
}
}
}
This is fairly simple, once you add the row:
You need to set the edit index of the newly added row:
gv.EditIndex = gv.Rows.Count-1;
Edit for OP
This is dirty code, I am just showing you what I mean and whipped it up fairly quickly.
Assume a gridview called GridView1 on your page:
namespace HelpSO3
{
public partial class _Default : System.Web.UI.Page
{
List<string> t = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string s = "hi";
t.Add(s);
GridView1.DataSource = t;
GridView1.DataBind();
Session["MyList"] = t;
}
}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
t = (List<string>)Session["MyList"];
t.Add("Another String");
GridView1.DataSource = t;
GridView1.DataBind();
GridView1.EditIndex = GridView1.Rows.Count - 1;
GridView1.DataBind();
Session["MyList"] = t;
}
}
}
So the Button1_Click event adds a new row with the value "Another String" then we bind the grid view and set the EditIndex value to the newest row and rebind. Its that simple.
In your case your code would become:
protected void gv_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Insert") //- this is needed to explain that the INSERT command will only work when INSERT is clicked
{
dbcon.Execute("INSERT INTO PROJ_ASP (TRANS_CD) VALUES('')", "ProjectASPConnectionString");
gv.DataBind();
gv.EditIndex = gv.Rows.Count-1;
gv.DataBind();
}
}
When I dynamically create a Datagrid and add in a new buttoncolumn how do I access the buttoncolumn_click event?
Thanks.
protected void Page_Load(object sender, EventArgs e)
{
DataGrid dg = new DataGrid();
dg.GridLines = GridLines.Both;
dg.Columns.Add(new ButtonColumn {
CommandName = "add",
HeaderText = "Event Details",
Text = "Details",
ButtonType = ButtonColumnType.PushButton
});
dg.DataSource = getDataTable();
dg.DataBind();
dg.ItemCommand += new DataGridCommandEventHandler(dg_ItemCommand);
pnlMain.Controls.Add(dg);
}
protected void dg_ItemCommand(object source, DataGridCommandEventArgs e)
{
if (e.CommandName == "add")
{
throw new Exception("add it!");
}
}
protected DataTable getDataTable()
{
// returns your data table
}
This article on the MSDN site clearly explains how to go about adding a button into a datagrid. Instead of using the click event of the button you'll use the command event of the DataGrid. Each button will be passing specific commandarguments that you will set.
This article shows how to use the command event with buttons. In it you use CommandArguments and CommandNames.
Here is where I create the datagrid:
System.Web.UI.WebControls.DataGrid Datagridtest = new System.Web.UI.WebControls.DataGrid();
Datagridtest.Width = 600;
Datagridtest.GridLines = GridLines.Both;
Datagridtest.CellPadding = 1;
ButtonColumn bc = new ButtonColumn();
bc.CommandName = "add";
bc.HeaderText = "Event Details";
bc.Text = "Details";
bc.ButtonType = System.Web.UI.WebControls.ButtonColumnType.PushButton;
Datagridtest.Columns.Add(bc);
PlaceHolder1.Controls.Add(Datagridtest);
Datagridtest.DataSource = dt;
Datagridtest.DataBind();
And here is the event I am trying to use:
protected void Datagridtest_ItemCommand(object source, DataGridCommandEventArgs e)
{
....
}
Thought that might help because I can't seem to capture the event at all.