How to determine which button is clicked in dynamically created DataTable - asp.net

I'm creating dynamically data Table bound to Grid View. Every row is populated with button. When i determine which button is clicked on the row, i want to get the current value of cell in clicked button in that row and modify her.Help!
Markup
<asp:GridView ID="GridView2" runat="server"
OnRowDataBound="GridView2_RowDataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btnTest" runat="server"
CommandName="odzemi"
CssClass="button2"
Font-Bold="True"
Text="-"
Width="100px"
OnClick="btnTest_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
//in this way a create row
private void AddNewRecordRowToGrid()
{
int counter;
if (Request.Cookies["kasa"] == null)
counter = 0;
else
{
counter = int.Parse(Request.Cookies["kasa"].Value);
}
counter++;
Response.Cookies["kasa"].Value = counter.ToString();
Response.Cookies["kasa"].Expires = DateTime.Now.AddYears(2);
if (ViewState["Markici"] != null)
{
DataTable dtCurrentTable = (DataTable)ViewState["Markici"];
DataRow drCurrentRow = null;
if (dtCurrentTable.Rows.Count > 0)
{
for (int i = 1; i <= dtCurrentTable.Rows.Count; i++)
{
HttpCookie cookie = Request.Cookies["Democookie"];
drCurrentRow = dtCurrentTable.NewRow();
drCurrentRow["FirmaID"] = Request.Cookies["firma"].Value;
drCurrentRow["Godina"] = Request.Cookies["godina"].Value;
drCurrentRow["KasaID"] = Request.Cookies["kasa"].Value;
drCurrentRow["MarkicaID"] = Request.Cookies["kasa"].Value;
drCurrentRow["Datum"] = DateTime.Now;
drCurrentRow["Masa"] = Session["masa39"];
drCurrentRow["VrabotenID"] = Session["New"];
drCurrentRow["Artikal"] = Label3.Text;
drCurrentRow["Cena1"] = Label4.Text;
//this is where i need to make changes
drCurrentRow["Kolicina"] = Label5.text;
drCurrentRow["Smena"] = Session["smena1"];
drCurrentRow["VkIznos"] = Label6.Text;
drCurrentRow["VkDanok"] = Label8.Text;
drCurrentRow["SySDatum"] = DateTime.Now;
drCurrentRow["Vid"] = Label23.Text;
drCurrentRow["Edmera"] = Label10.Text;
drCurrentRow["ArtikalID"] = Label33.Text;
}
//Removing initial blank row
if (dtCurrentTable.Rows[0][0].ToString() == "")
{
dtCurrentTable.Rows[0].Delete();
dtCurrentTable.AcceptChanges();
}
//Added New Record to the DataTable
dtCurrentTable.Rows.InsertAt(drCurrentRow,0);
//storing DataTable to ViewState
ViewState["Markici"] = dtCurrentTable;
//binding Gridview with New Row
GridView2.DataSource = dtCurrentTable;
GridView2.DataBind();
}
}
}
//in this button i call that method
protected void Button9_Click(object sender, EventArgs e)
{
AddNewRecordRowToGrid();
}
//
and here i'm determine clicked button of row, and here in this
dtCurrentTable.Rows[clickedIndex]["Kolicina"]= "" i need to
get cureent value of cell which is different in every row.
protected void btnTest_Click(object sender, EventArgs e)
{
DataTable dtCurrentTable = (DataTable)ViewState["Markici"];
var clickedRow = ((Button)sender).NamingContainer as GridViewRow;
var clickedIndex = clickedRow.RowIndex;
//so here i want to get current value of cell, and modify her
dtCurrentTable.Rows[clickedIndex]["Kolicina"] = " ";
GridView2.DataSource = dtCurrentTable;
GridView2.DataBind();
}

Try this.
protected void btnTest_Click(object sender, EventArgs e)
{
var clickedRow = ((Button)sender).NamingContainer as GridViewRow;
var clickedIndex = clickedRow.RowIndex;
}
Provided your GridView does not have sorting or paging enabled, from this clickedIndex, we can get the corresponding Row of the DataTable like this.
dtCurrentTable.Rows[clickedIndex]["Kolicina"] = "StackOverflow";

In the RowDataBound event, the EventArgument e should have the index of the current item bound in it. The code e.Row.RowIndex will return the index of the row in the Grid, not necessarily the datasource when you have paging applied. There is a 'DataItemIndex' property, another index that may give you what you are looking for, depending on what you are trying to do.
The grid also exposes the Rows collection, which you can use a foreach to loop through each one, and access that way too.
Note, the Rows on postback will only be based on the markup posted back through viewstate; the grid knows nothing about your data source (unless you rebind on every postback).

Related

Hiding Columns in Gridview when grid view is empty

I have a grid view on which i am hiding some columns. it gives me expected result when there is at least one item in grid view but when my grid is empty then it shows hidden columns. what to do how to solve it when there is no record means grid view is empty then it also hides the columns that has been made hidden i am hiding columns in OnitemDataBound(object sender, GridItemEventArgs e) event of grid.
Put the Hidden column data in DatakeysName property of Gridview. Then it will not show any column. You can get that for further use. If you want to show no data found message, then set EmptyDataText="No Data Found!!!".
Assuming that if there is no data coming from the server you want to hide the column names or something like that. You can use empty template feature of grid view. Go to the designer mode click quick property of grid view. Go to the templates and select the empty template. Then write some text or message like "No record found." and run the code. You do not need to write any server side code for this.
The Column should be made hidden using the code.
1. The logic should be such that we loop through the rows and see if the column does not have values for all the rows.
2. if the value does not exist for the column only then make the column hidden.
3. this entire logic should be implemented in prerender event.
I can provide you sample code tonight...
here is the sample code...
protected void GridView1_PreRender(object sender, EventArgs e)
{
bool isColumnEmpty = true;
int columnIndex =2;
for (int i = 0; i < GridView1.Rows.Count; i++)
{
if (GridView1.Rows[i].Cells[columnIndex].ToString() != string.Empty)
{
isColumnEmpty = false;
break;
}
}
if (isColumnEmpty)
{
GridView1.Columns[columnIndex].Visible = false;
}
}
Full Code Sample
ASPX Code :
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
onprerender="GridView1_PreRender">
<Columns>
<asp:BoundField DataField="dc1" HeaderText="Column - 1" />
<asp:BoundField DataField="dc2" HeaderText="Column - 2" />
<asp:BoundField DataField="dc3" HeaderText="Column - 3" />
<asp:BoundField DataField="dc4" HeaderText="Column - 4" />
<asp:BoundField DataField="dc5" HeaderText="Column - 5" />
</Columns>
</asp:GridView>
</div>
</form>
CS Code :
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
GridView1.DataSource = GetDataSet();
GridView1.DataBind();
}
private DataSet GetDataSet()
{
DataSet ds = new DataSet();
DataTable dt = new DataTable();
DataColumn dc1 = new DataColumn("dc1");
DataColumn dc2 = new DataColumn("dc2");
DataColumn dc3 = new DataColumn("dc3");
DataColumn dc4 = new DataColumn("dc4");
DataColumn dc5 = new DataColumn("dc5");
dt.Columns.Add(dc1);
dt.Columns.Add(dc2);
dt.Columns.Add(dc3);
dt.Columns.Add(dc4);
dt.Columns.Add(dc5);
for (int i = 0; i < 10; i++)
{
DataRow dr = dt.NewRow();
dr[dc1] = i;
//dr[dc2] = "2" + i.ToString();
dr[dc3] = "3"+ i.ToString();
dr[dc4] = "4" + i.ToString();
dr[dc5] = "5" + i.ToString();
dt.Rows.Add(dr);
}
ds.Tables.Add(dt);
return ds;
}
protected void GridView1_PreRender(object sender, EventArgs e)
{
bool isColumnEmpty = true;
int columnIndex =2;
for (int i = 0; i < GridView1.Rows.Count; i++)
{
if (GridView1.Rows[i].Cells[columnIndex].ToString() != string.Empty)
{
isColumnEmpty = false;
break;
}
}
if (isColumnEmpty)
{
GridView1.Columns[columnIndex].Visible = false;
}
}
}

find a control by id from Dynamically added Template field in GridView

Hi i added template field dynamically to gridview by implementing ITemplate interface.
The template field contains some controls like label and textboxes. how do i get these controls in row databound event.
I am not able to get when i do gridviewrow.findcontrol("id") as i do normally when we add templatefield from aspx page.
The way i added template field is like this
public class CustomGridViewColumn : ITemplate
{
ListItemType _liType;
string _columnName;
public CustomGridViewColumn(ListItemType type, string column)
{
_liType = type;
_columnName = column;
}
void ITemplate.InstantiateIn(System.Web.UI.Control container)
{
switch (_liType)
{
case ListItemType.Header:
Label lblHeader = new Label();
lblHeader.Text = _columnName;
container.Controls.Add(lblHeader);
break;
case ListItemType.Item:
Label lblItem = new Label();
lblItem.DataBinding += new EventHandler(lbl_DataBinding);
lblItem.ID = "lbl" + _columnName;
lblItem.ClientIDMode = ClientIDMode.Predictable;
container.Controls.Add(lblItem);
DropDownList ddl = new DropDownList();
ddl.DataBinding += new EventHandler(ddl_DataBinding);
ddl.ID = "ddl" + _columnName;
ddl.Visible = false;
container.Controls.Add(ddl);
break;
}
}
}
Now i want access the label and dropdown which i have added using this code.
when i do gridviewrow.findcontrol("id") i am not getting them.
Can any one please help me.
I am geeting when i go through all the rows and try to find but
i have a check box in a row when i select it all labels should diappear and ddls dhould appear
for this i am using the follwoing code.
protected void chkEdit_CheckedChanged(object sender, EventArgs e)
{
CheckBox chkEditTest = (CheckBox)sender;
GridViewRow grow = (GridViewRow)chkEditTest.NamingContainer;
DropDownList ddl = (DropDownList)grow.FindControl("ddl");
Label lbl= (Label)grow.FindControl("lbl");
}
when i do this i am not able to get the controls.
it seems like controls are disapppearing on postback..
This is what I came up with and I can able to get the control reference in the code behind.
public class CustomGridViewColumn : ITemplate
{
ListItemType _liType; string _columnName;
public CustomGridViewColumn(ListItemType type, string column)
{
_liType = type;
_columnName = column;
}
void ITemplate.InstantiateIn(Control container)
{
switch (_liType)
{
case ListItemType.Header:
Label lblHeader = new Label();
lblHeader.Text = _columnName;
container.Controls.Add(lblHeader);
break;
case ListItemType.Item:
Label lblItem = new Label();
lblItem.DataBinding += new EventHandler(lblItem_DataBinding);
lblItem.ID = "lbl" + _columnName;
lblItem.ClientIDMode = ClientIDMode.Predictable;
container.Controls.Add(lblItem);
DropDownList ddl = new DropDownList();
ddl.DataBinding += new EventHandler(ddl_DataBinding);
ddl.ID = "ddl" + _columnName;
ddl.Visible = false;
ddl.DataSource = new string[] { "Hello", "World" };
container.Controls.Add(ddl);
break;
}
}
void ddl_DataBinding(object sender, EventArgs e)
{
}
void lblItem_DataBinding(object sender, EventArgs e)
{
}
}
protected void Page_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("Name");
DataRow oItem = dt.NewRow();
oItem[0] = "Deepu";
dt.Rows.Add(oItem);
oItem = dt.NewRow();
oItem[0] = "MI";
dt.Rows.Add(oItem);
GridView gv = new GridView();
gv.ID = "myGridView";
gv.AutoGenerateColumns = false;
BoundField nameColumn = new BoundField();
nameColumn.DataField = "Name";
nameColumn.HeaderText = "Name";
gv.Columns.Add(nameColumn);
TemplateField TmpCol = new TemplateField();
TmpCol.HeaderText = "Template Column";
gv.Columns.Add(TmpCol);
TmpCol.ItemTemplate = new CustomGridViewColumn(ListItemType.Item, "TEST");
gv.DataSource = dt;
gv.DataBind();
Form.Controls.Add(gv);
}
protected void Button1_Click(object sender, EventArgs e)
{
GridView gv = Form.FindControl("myGridView") as GridView;
foreach (GridViewRow item in gv.Rows)
{
var ddl = item.FindControl("ddlTest") as DropDownList;
if (ddl != null)
{
ddl.Visible = true;
}
var lbl = item.FindControl("lbl") as Label;
if (lbl != null)
{
lbl.Text = "hello";
}
}
}
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
</form>
Thanks
Deepu
Can you try using row index of GRIDVIEW control
var rowIndex = int.Parse(e.CommandArgument)
GridView1.Rows[rowIndex].FindControl("id")
Also refer
http://forums.asp.net/t/998368.aspx/1
http://www.codeproject.com/Articles/12021/Accessing-the-different-controls-inside-a-GridView
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridviewrow.aspx
Thanks
Deepu

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...
}
}

Save values on Postback

I have been doing custom paging for a datagrid where i retrieve only 10 values per page. So, I started doing it this way :
<asp:GridView ID="grid1" runat="server"
> </asp:GridView>
<asp:Button ID="Btn_Previous" CommandName="Previous" runat="server"
OnCommand="ChangePage" Text="Previous" />
<asp:Button ID="Btn_Next" runat="server" CommandName="Next" OnCommand="ChangePage"
Text="Next" />
<asp:Label ID="lblTotalPages" runat="server"></asp:Label>
<asp:Label ID="lblCurrentPage" runat="server"></asp:Label>
protected int currentPageNumber = 1;
protected const int PAGE_SIZE = 10;
protected int startrowindex=1;
protected void Page_Load(object sender, EventArgs e)
{
BindData();
}
private void BindData()
{
using (SqlConnection conn = new SqlConnection("Data Source=NISHANTH-PC\\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True"))
{
conn.Open();
SqlCommand myCommand = new SqlCommand("GetProductsPaged",
conn);
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.Parameters.AddWithValue("#startRow",
startrowindex);
myCommand.Parameters.AddWithValue("#maximumRows", PAGE_SIZE);
myCommand.Parameters.Add("#totalRows", SqlDbType.Int, 4);
myCommand.Parameters["#totalRows"].Direction = ParameterDirection.Output;
SqlDataAdapter ad = new SqlDataAdapter(myCommand);
DataSet ds = new DataSet();
ad.Fill(ds);
grid1.DataSource = ds;
grid1.DataBind();
double totalRows = (int)myCommand.Parameters["#totalRows"].Value;
lblTotalPages.Text = CalculateTotalPages(totalRows).ToString();
lblCurrentPage.Text = currentPageNumber.ToString();
if (currentPageNumber == 1)
{
Btn_Previous.Enabled = false;
if (Int32.Parse(lblTotalPages.Text) > 0)
{
Btn_Next.Enabled = true;
}
else
Btn_Next.Enabled = false;
}
else
{
Btn_Previous.Enabled = true;
if (currentPageNumber == Int32.Parse(lblTotalPages.Text))
Btn_Next.Enabled = false;
else Btn_Next.Enabled = true;
}
conn.Close();
}
}
private int CalculateTotalPages(double totalRows)
{
int totalPages = (int)Math.Ceiling(totalRows / PAGE_SIZE);
return totalPages;
}
protected void ChangePage(object sender, CommandEventArgs e)
{
switch (e.CommandName)
{
case "Previous":
currentPageNumber = currentPageNumber - 1;
startrowindex = startrowindex - 10;
break;
case "Next":
currentPageNumber = currentPageNumber + 1;
startrowindex = startrowindex + 10;
break;
}
BindData();
}
Basically, my problem has been that the grid works fine when the page loads. Then, since previous is hidden, when i click next it goes to second page and retrieves values perfectly. But when i click either on next or previous now, it goes all wrong. The reason i think is that, when I come back the currentpagenumber value at top is again becoming 1and startroeindex also becomes 1. Can u please let me know the way i can handle this?
I don't know your aspx page, but you need a way to send the previous page number. Otherwise, your script doesn't know what next means except 1+1. How do you change pages? Hyperlinks? If so, send the last page in a form field or query string.
first thing is that you are loading BindData on each and every post back, you must only call it on first time load.
Second thing, you are storing the in label, lblCurrentPage.Text = currentPageNumber.ToString(); So why dont you utilize the same and store it again on page_load event.
I have here provided the page_load event try this.
protected void Page_Load(object sender, EventArgs e)
{
currentPageNumber = Convert.ToInt32(lblCurrentPage.Text);
if(!IsPostback)
{
BindData();
}
}
please add default value for lblCurrentPage.Text to 1.

asp.net - GridView dynamic footer row creation problem

I am able to create BoundFields and Footer-rows dynamically like this in my GridView:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
CreateGridView();
}
}
private void CreateGridView()
{
GridView1.Columns.Clear();
DataTable dataTable = Book.GetBooksDataSet().Tables[0];
CommandField cf = new CommandField();
cf.ShowEditButton = true;
GridView1.Columns.Add(cf);
int colCount = 1;
foreach (DataColumn c in dataTable.Columns)
{
BoundField boundField = new BoundField();
boundField.DataField = c.ColumnName;
boundField.HeaderText = c.ColumnName;
//boundField.FooterText = "---";
if (colCount == 3 || colCount == 5)
{
boundField.ReadOnly = true;
}
GridView1.Columns.Add(boundField);
colCount++;
}
GridView1.ShowFooter = true;
GridView1.DataSource = dataTable;
GridView1.DataBind();
GridViewRow footerRow = GridView1.FooterRow;
Button b = new Button();
b.Text = "Add New";
int i = 0;
footerRow.Cells[i].Controls.Add(b);
foreach (DataColumn c in dataTable.Columns)
{
++i;
TextBox tb = new TextBox();
footerRow.Cells[i].Controls.Add(tb);
}
}
....................................
....................................
....................................
}
But the problem is, when I click the "Add New" - button, it disappears instantly. And, also I am unable to add any event handler to it. Or intercept its actions like this:
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
int index = Convert.ToInt32(e.CommandArgument);
if (e.CommandName == "Edit")
{
GridView1.EditIndex = index;
GridViewRow selectedRow = ((GridView)e.CommandSource).Rows[index];
//We can get cell data like this
string id = selectedRow.Cells[1].Text;
string isbn = selectedRow.Cells[2].Text;
//This is necessary to GridView to be showed up.
CreateGridView();
}
else if (e.CommandName == "Update")
{
LinkButton updateButton = (LinkButton)e.CommandSource;
DataControlFieldCell dcfc = (DataControlFieldCell)updateButton.Parent;
GridViewRow gvr = (GridViewRow)dcfc.Parent;
//The update...................
//Update grid-data to database
UpdateDataInTheDatabase(gvr.Cells[1].Controls);
//Grid goes back to normal
GridView1.EditIndex = -1;
//This is necessary to GridView to be showed up.
CreateGridView();
}
}
One more thing, I have seen some solutions that suggests to handle the GridView's rowBound event. But I need to do it from within Page_load event handler, or in, GridView1_RowCommand event handler.
Dynamically created controls mus be re-created on every postback. Your "Add New" button causes a postback so the dynamically created footer disappears. Is there a reason this grid has to be created dynamically? From the code you posted it appears that you could do this in markup instead. If not, you'll have to re-create the dynamic controls on every postback.
Edited to add:
I played with this a little bit and what's below works in that the grid doesn't disappear and events are handled, but it doesn't actually do anything. Hope this helps.
Markup:
<p><asp:Literal ID="Literal1" runat="server" /></p>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"
OnRowCommand="GridView1_RowCommand"
OnRowEditing="GridView1_RowEditing"/>
Code:
protected void Page_Load(object sender, EventArgs e)
{
BindGridView();
}
private DataTable GetBooksDataTable()
{
var dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Title", typeof(string));
dt.Columns.Add("Author", typeof(string));
for (int index = 0; index < 10; index++)
{
dt.Rows.Add(index, "Title" + index, "Author" + index);
}
return dt;
}
private void BindGridView()
{
var dt = GetBooksDataTable();
GridView1.Columns.Clear();
GridView1.ShowFooter = true;
var cf = new CommandField();
cf.HeaderText = "Action";
cf.ShowEditButton = true;
GridView1.Columns.Add(cf);
for (int index = 0; index < dt.Columns.Count; index++)
{
var boundField = new BoundField();
boundField.DataField = dt.Columns[index].ColumnName;
boundField.HeaderText = dt.Columns[index].ColumnName;
GridView1.Columns.Add(boundField);
}
GridView1.DataSource = dt;
GridView1.DataBind();
var footer = GridView1.FooterRow;
var b = new LinkButton();
b.Text = "Add New";
b.CommandName = "Add New";
footer.Cells[0].Controls.Add(b);
for (int index = 1; index < dt.Columns.Count + 1; index++)
{
var tb = new TextBox();
footer.Cells[index].Controls.Add(tb);
}
}
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
Literal1.Text = e.CommandName;
}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
Literal1.Text = "Editing row index " + e.NewEditIndex.ToString();
}
Move your code from Page_Load to Page_Init. Things added in the Page_Load last only for the lifecycle of one postback.
You'd then be able to add eventhandlers, intercept events etc.

Resources