How to add a row in asp.net grid view - asp.net

So far I have done this, I am not sure whether this is right or wrong
public partial class _Default : System.Web.UI.Page
{
Label l = new Label();
GridView gv = new GridView();
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 0; i < 5; i++)
{
GridViewRow gvr = new GridViewRow(i, i, DataControlRowType.DataRow, DataControlRowState.Normal);
gvr.Controls.Add(l);
gv. (what to do here)
}
this.Controls.Add(gv);
}
}
please help

gv.Rows.Add(gvr);
If you're starting with an empty GridView, an easier way to dynamically create x rows is to create a dummy list and then set it to the data source:
var list = new List<string>(10); // replace 10 with number of empty rows you want
// for loop to add X items to the list
gv.DataSource = list;
gv.DataBind();
If you are doing this, I'd recommend doing it with a Repeater. It's a lot easier to manage.

The DataGrid fires the RowCreate event when a new row is created.
Collapse
//OnRowCreated="GridView3_RowCreated"
protected void GridView3_RowCreated(object sender, GridViewRowEventArgs e)
{
//When a child checkbox is unchecked then the header checkbox will also be unchecked.
if (e.Row.RowType == DataControlRowType.DataRow && (e.Row.RowState ==
DataControlRowState.Normal || e.Row.RowState == DataControlRowState.Alternate))
{
CheckBox chkBxSelect = (CheckBox)e.Row.Cells[1].FindControl("chkselect");
CheckBox chkBxHeader = (CheckBox)this.GridView3.HeaderRow.FindControl("chkHeader");
chkBxSelect.Attributes["onclick"] = string.Format("javascript:ChildClick(
this,'{0}');", chkBxHeader.ClientID);
}
}

Related

How to access dynmaically added Textbox values ASP.Net

I have a gridview placed on a ASP.Net WebSite, and added a column dynamically like this:
protected void gvGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (DataControlRowType.DataRow == e.Row.RowType && e.Row.RowState != DataControlRowState.Edit &&
(e.Row.RowState == DataControlRowState.Normal || e.Row.RowState == DataControlRowState.Alternate))
{
TextBox tb = new TextBox();
tb.ID = "tb";
tb.Attributes.Add("runat", "server");
int i = e.Row.Cells.Count;
i = i - 1;
e.Row.Cells[i].Controls.Add(tb);
}
}
The gridview is populated, and at the end of every row the TextBox is added. When I look at the HTML Code that is delived to the Browser, I can see that the ID of every Textbox is "gv_Items_tb_X" with X being the current row index.
Now I would like to access the content that the user types in the tb on a button click. I tried following code, but it I get an exception becuase the textbox is null.
protected void btn_UpdateCount_Click(object sender, EventArgs e)
{
OI_Data_Service.OI_Data_ServiceClient sc = new OI_Data_Service.OI_Data_ServiceClient();
foreach (GridViewRow row in gv_Items.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
TextBox tb_value = (TextBox)gv_Items.Rows[row.RowIndex].Cells[5].FindControl("gv_Items_tb_" + row.RowIndex);
sc.UpdateItemOnOpening("1", row.Cells[0].Text, tb_value.Text);
}
}
Response.Redirect("~/okay.aspx");
}
Can anyone tell my what I am doing wrong?
Thanks!

parent grid rowindex from child grid button click ASP.net

I gave a nested grid. while clicking on a button in child grid I have to get parent grid row index. I have used like this type of code
protected void GridView2_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "go")
{
GridViewRow Gv2Row = (GridViewRow)((LinkButton)e.CommandSource).NamingContainer;
GridView Childgrid = (GridView)(Gv2Row.Parent.Parent);
GridViewRow Gv1Row = (GridViewRow)(Childgrid.NamingContainer);
GridView Parentgrid = (GridView)(Gv1Row.Parent.Parent);
}
}
but it's not working..
Showing typecasting error . How to solve that..
Please try with the below code snippet.
protected void GridView2_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "go")
{
GridViewRow Gv2Row = (GridViewRow)((LinkButton)sender).NamingContainer;
GridView Childgrid = (GridView)(Gv2Row.Parent.Parent);
GridViewRow Gv1Row = (GridViewRow)(Childgrid.NamingContainer);
int b = Gv1Row.RowIndex;
// Access your parent grid index here
}
}
You are missing an extra ( and ) for the code in commented line below resulting in typecasting error. And you don't need the last statement in your code because you have already found the parent grid.
I would suggest you better change the naming convention for the parent/child gridview/row object in your code to make it understand better as detailed below.
if (e.CommandName == "go")
{
// GridViewRow Gv2Row = (GridViewRow)((LinkButton)e.CommandSource).NamingContainer;
GridViewRow childrow = (GridViewRow)(((LinkButton)e.CommandSource).NamingContainer);
GridView parentgrid = (GridView)(childrow.Parent.Parent);
GridViewRow parentrow = (GridViewRow)(parentgrid.NamingContainer);
int parentrowindex = parentrow.RowIndex;
}

Dynamic template field in grdivew post back values

//Bedlow is the page_load code to add dynamic controls in page load. and load of page_load
gvSecond 's dynamic template fields will be added.I want to know why the dot is appended on each postback values
protected void Page_Load(object sender, EventArgs e)
{
gvFirst.DataSource = GetData("select top 10 * from Project_Master");
gvFirst.DataBind();
}
//gvFirst has gvSecond and on rowdatabound of the gvFirst gvSecond populated with dynamic template fields. and all the template fields has the TextBoxtes in it
protected void gvFirst_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
//below code to generate dynamic template column
gvFirst.DataSource = GetData("select top 10 * from Project_Master");
gvFirst.DataBind();
//Added dynamic controls in gvSecond
protected void gvFirst_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string customerId = gvFirst.DataKeys[e.Row.RowIndex].Value.ToString();
GridView gvSecond = e.Row.FindControl("gvSecond") as GridView;
DataTable dt= GetData1(Convert.ToInt32(customerId));
foreach (DataColumn col in dt.Columns)
{
//Declare the bound field and allocate memory for the bound field.
TemplateField bfield = new TemplateField();
//Initalize the DataField value.
bfield.HeaderTemplate = new GridViewTemplate(ListItemType.Header, col.ColumnName);
//Initialize the HeaderText field value.
bfield.ItemTemplate = new GridViewTemplate(ListItemType.Item, col.ColumnName);
//Add the newly created bound field to the GridView.
gvSecond.Columns.Add(bfield);
}
TotalColumns = dt.Columns.Count;
gvSecond.DataSource = dt;
gvSecond.DataBind();
}
}
}
//This is used to add the dynamic template in gvSecond.Now when I click on button textbox values appended with postback values and older values seperated by dot(.)
You need to wrap the code in Page_Load in if(!IsPostback){}:
EDIT :
Edited to create second grid at postback.
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
gvFirst.DataSource = GetData("select top 10 * from Project_Master");
gvFirst.DataBind();
}
else
{
CreateSecondGridView();
}
}
And your Rowdatabound may look like this:
protected void gvFirst_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
CreateSecondGridView();
}
protected void CreateSecondGridView()
{
foreach(GridViewRow row in gvFirst.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
string customerId = gvFirst.DataKeys[row.RowIndex].Value.ToString();
GridView gvSecond = row.FindControl("gvSecond") as GridView;
DataTable dt= GetData1(Convert.ToInt32(customerId));
foreach (DataColumn col in dt.Columns)
{
//Declare the bound field and allocate memory for the bound field.
TemplateField bfield = new TemplateField();
//Initalize the DataField value.
bfield.HeaderTemplate = new GridViewTemplate(ListItemType.Header, col.ColumnName);
//Initialize the HeaderText field value.
bfield.ItemTemplate = new GridViewTemplate(ListItemType.Item, col.ColumnName);
//Add the newly created bound field to the GridView.
gvSecond.Columns.Add(bfield);
}
TotalColumns = dt.Columns.Count;
gvSecond.DataSource = dt;
gvSecond.DataBind();
}
}
}

Prepopulate gridview empty datasource

I use an gridview empty datasource for bulk insert, how would I prepopulate for instance Column A with the value of a drop down box? So far I have below, but its not working
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
TextBox tb = (TextBox)e.Row.FindControl("YourTextBoxID");
if(tb != null)
{
tb.Text = DropDownList1.SelectedItem.Text;
}
}
}
I don't understand what you mean with empty DataSource. I assume that you actully mean a DataSource which is populated automatically with a default value.
You could use a DataTable:
var tbl = new DataTable();
tbl.Columns.Add("ColumnA");
var defText = DropDownList1.SelectedItem.Text;
for(int i = 0; i < 1000; i++)
{
tbl.Rows.Add(defText);
}
GridView1.DataSource = tbl;
GridView1.DataBind();

How to add an extra row (containing a Button and corresponding event handler) to the GridView

This must be something that a lot of people have done. Basically, it's a custom GridView (i.e. inherited control) with the ability to update all rows at once. I've tried putting the "update all" button in various places (footer, pager, outside the grid), but it looks neatest (to me) when the button is in an extra row as the last row of the GridView.
NB: The pager row is not a suitable place for this button because this custom control could be used in a situation where paging is false. Similarly, the normal footer may be required for some other purpose (e.g. totals).
Here's my code for putting the button in the correct place (with apologies for the terse variables etc.):
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
//Add an extra row to the table...
if (_updateAllEnabled)
{
GridViewRow r = base.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal);
Button btn = new Button();
TableCell c = new TableCell();
btn.ID = "UpdateAllButton"; // tried with and without this line
btn.Text = "Update All";
btn.Click += new EventHandler(UpdateAll);
r.Cells.Add(c);
c.Controls.Add(btn);
Table t = this.Controls[0] as Table;
c.ColumnSpan = this.Columns.Count;
t.Rows.Add(r);
}
}
This gives the appearance that I want, but the click event (UpdateAll) does not fire.
I assume that the stuff is being added too late in the life cycle (PreRender), but where else can I do this to ensure that the row is at the end of the GridView? I also thought that there might be trouble identifying the button, so I tried setting the ID. In any case, the ID in the generated HTML looks OK (consistent with "working" buttons in the pager row.
Is there a way for me to achieve this or am I attempting the impossible?
The best place to create your footer-controls is RowCreated since that's early enough in the lifecycle and also ensures that their recreated on every postback:
Footer approach:
protected void Grid_RowCreated(Object sender, GridViewRowEventArgs e) {
if(e.Row.RowType == DataControlRowType.Footer) {
Button btn = new Button();
TableCell c = new TableCell();
btn.ID = "UpdateAllButton";
btn.Text = "Update All";
btn.Click += new EventHandler(UpdateAll);
var firstCell=e.Row.Cells[0];
firstCell.ColumnSpan =e.Row.Cells.Count;
firstCell.Controls.Add(btn);
while(e.Row.Cells.Count > 1)e.Row.Cells.RemoveAt(e.Row.Cells.Count-1);
}
}
Of course you have to set ShowFooter to true:
<asp:GridView ID="GridView1"
ShowFooter="true"
OnRowCreated="Grid_RowCreated"
runat="server"
</asp:GridView>
Pager approach:
In my opinion this is the purpose of the FooterRow. But if you really want to ensure that your Button is in the very last row of a GridView(even below Pager as commented), i would try my next approach.
Here I'm using the pager for your costom control(s) by adding another TableRow to the PagerTable which inherits from Table.
protected void Grid_RowCreated(Object sender, GridViewRowEventArgs e) {
switch(e.Row.RowType){
case DataControlRowType.Pager:
Button btnUpdate = new Button();
btnUpdate.ID = "UpdateButton";
btnUpdate.Text = "Update";
btnUpdate.Click += new EventHandler(UpdateAll);
var tblPager = (Table)e.Row.Cells[ 0 ].Controls[ 0 ];
var row = new TableRow();
var cell = new TableCell();
cell.ColumnSpan = tblPager.Rows[ 0 ].Cells.Count;
cell.Controls.Add(btnUpdate);
row.Cells.Add(cell);
tblPager.Rows.Add(row);
break;
}
}
To ensure that the pager is visible even if only one page is shown(note that the real pager is invisible if PageSize==1):
protected void Grid_PreRender(object sender, EventArgs e){
GridView gv = (GridView)sender;
GridViewRow gvr = (GridViewRow)gv.BottomPagerRow;
if(gvr != null) {
gvr.Visible = true;
var tblPager = (Table)gvr.Cells[ 0 ].Controls[ 0 ];
//hide real pager if unnecessary
tblPager.Rows[ 0 ].Visible = GridView1.PageCount > 1;
}
}
Of course now you have to set AllowPaging=true:
<asp:GridView ID="GridView1"
AllowPaging="true"
PagerSettings-Mode="NumericFirstLast"
OnRowCreated="Grid_RowCreated"
OnPreRender="Grid_PreRender"
OnPageIndexChanging="Grid_PageChanging"
runat="server">
</asp:GridView>
Final approach(working for a custom GridView and all PagerPositions):
public PagerPosition OriginalPagerPosition{
get { return (PagerPosition)ViewState[ "OriginalPagerPosition" ]; }
set { ViewState[ "OriginalPagerPosition" ] = value; }
}
protected void Page_Load(object sender, EventArgs e){
if(!IsPostBack) OriginalPagerPosition = GridView1.PagerSettings.Position;
GridView1.PagerSettings.Position = PagerPosition.TopAndBottom;
GridView1.AllowPaging = true;
// databinding stuff ...
}
Keep the RowCreated the same as above in Pager approach.
Visibility of top/bottom pagers will be controlled in PreRender according to the OriginalPagerPosition property. Both pagers are created even with PagerPosition=TOP, the bottom pager is required for your additional control(s):
protected void Grid_PreRender(object sender, EventArgs e)
{
GridView gv = (GridView)sender;
GridViewRow tpr = (GridViewRow)gv.TopPagerRow;
GridViewRow bpr = (GridViewRow)gv.BottomPagerRow;
tpr.Visible = gv.PageCount > 1 && (OriginalPagerPosition == PagerPosition.Top || OriginalPagerPosition == PagerPosition.TopAndBottom);
bpr.Visible = true;
var tblBottomPager = (Table)bpr.Cells[ 0 ].Controls[ 0 ];
tblBottomPager.Rows[ 0 ].Visible = gv.PageCount > 1 && (OriginalPagerPosition == PagerPosition.Bottom || OriginalPagerPosition == PagerPosition.TopAndBottom);
var tblTopPager = (Table)tpr.Cells[ 0 ].Controls[ 0 ];
tblTopPager.Rows[1].Visible = false;
}
Note: if you are extending the GridView control, you have to replace all occurences of GridView1(my test-grid) with this.
It would be easy to add an extra row into the grid. But the difficulty in your requirement is that the GridView's RowCollection should not contain this row since that would be error-prone. It should also be the very last row even if paging is enabled. This is (afaik) not possible.
Hence i've chosen to extend the pager with this functionality.
I'll add this as separate answer since my other is already too detailed and describes two different ways(footer,pager) to add controls to a GridView without extending it.
This approach extends a GridView as in your own requirement and is similar to my other pager-approach. But it's cleaner and only adds the additional row to the BottomPager. It woks also for every setting(AllowPaging=false,Pager-Position: Top,Bottom,BottomTop):
[DefaultProperty("EnableUpdateAll")]
[ToolboxData("<{0}:UpdateGridView runat=server></{0}:UpdateGridView>")]
public class UpdateGridView : GridView
{
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("true")]
[Localizable(true)]
public bool EnableUpdateAll
{
get
{
Object val = ViewState["EnableUpdateAll"];
return ((val == null) ? true : (bool)val);
}
set
{
ViewState["EnableUpdateAll"] = value;
}
}
private bool OriginalAllowPaging
{
get
{
Object val = ViewState["OriginalAllowPaging"];
return (bool)val;
}
set
{
ViewState["OriginalAllowPaging"] = value;
}
}
private PagerPosition OriginalPagerPosition
{
get
{
Object val = ViewState["OriginalPagerPosition"];
return (PagerPosition)val;
}
set
{
ViewState["OriginalPagerPosition"] = value;
}
}
protected override void OnInit(System.EventArgs e)
{
if (ViewState["OriginalPagerPosition"] == null)
OriginalPagerPosition = base.PagerSettings.Position;
if(OriginalPagerPosition != PagerPosition.Bottom)
PagerSettings.Position=PagerPosition.TopAndBottom;
if (ViewState["OriginalAllowPaging"] == null)
OriginalAllowPaging = base.AllowPaging;
base.AllowPaging = true;
}
protected override void OnRowCreated(GridViewRowEventArgs e)
{
switch (e.Row.RowType)
{
case DataControlRowType.Pager:
//check if we are in BottomPager
if (this.Rows.Count != 0 && this.EnableUpdateAll)
{
Button btnUpdate = new Button();
btnUpdate.ID = "BtnUpdate";
btnUpdate.Text = "Update";
btnUpdate.Click += new EventHandler(UpdateAll);
var tblPager = (Table)e.Row.Cells[0].Controls[0];
var row = new TableRow();
var cell = new TableCell();
cell.ColumnSpan = tblPager.Rows[0].Cells.Count;
cell.Controls.Add(btnUpdate);
row.Cells.Add(cell);
tblPager.Rows.Add(row);
}
break;
}
}
protected override void OnPreRender(EventArgs e)
{
bool bottomPagerVisible =
OriginalAllowPaging &&
PageCount > 1 &&
(OriginalPagerPosition == PagerPosition.Bottom || OriginalPagerPosition == PagerPosition.TopAndBottom);
BottomPagerRow.Visible = bottomPagerVisible || EnableUpdateAll;
var tblBottomPager = (Table)BottomPagerRow.Cells[0].Controls[0];
tblBottomPager.Rows[0].Visible = bottomPagerVisible;
}
private void UpdateAll(Object sender, EventArgs e)
{
// do something...
}
}

Resources