How to add dynamic n checkbox columns to gridview ASP.NET - asp.net

Ex: mypage.aspx?num=xxx
How can I add a num checkbox column to Gridview in mypages by code-behind?
I had added num columns to Datatable with parameter typeof(bool) but when I loaded mypage, the checkboxes were disabled so I can't check them.

This is my grid aspx code
<asp:GridView ID="gv" runat="server" AutoGenerateColumns="false">
<Columns>
</Columns>
</asp:GridView>
First of all add num number of template fields to your gridview
protected void Page_PreInit(object sender, EventArgs e)
{
int num = Request.QueryString["num"];
for (int i = 0; i < num; i++)
{
TemplateField tf = new TemplateField();
tf.HeaderText = "Status";
gv.Columns.Add(tf);
}
}
After adding template feilds, now we will add checkboxes to the gridview. We write a function to add checkboxes. Below is the code
private void AddCheckBox()
{
int num = Request.QueryString["num"];
for (int i = 0; i < num; i++)
{
foreach (GridViewRow row in gv.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
CheckBox cb = new CheckBox();
cb.Checked = true;
row.Cells[i].Controls.Add(cb);
}
}
}
}
Now place this function in your grid databound event.
protected void gv_DataBound(object sender, EventArgs e)
{
AddCheckBox();
}
At the end also call the function in the page load event so first time when grid loads it shows checkboxes are checked
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
AddCheckBox();
}
}
To check my code:
I add a bound feild to grid view and bind the grid view with a datatable:
<asp:GridView ID="gv" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="Data" HeaderText="Data" />
</Columns>
</asp:GridView>
and in code behind in page_load event i add the following code
DataTable dt = new DataTable();
dt.Columns.Add("Data");
DataRow dr = dt.NewRow();
dr[0] = "Test";
dt.Rows.Add(dr);
gv.DataSource = dt;
gv.DataBind();
and also made 1 change in the function AddCheckBox as
for (int i = 1; i < num + 1; i++)
The above change is made because I have a databound feild at index 0 of the grid view columns so I changed it to start from 1.
and here is the result ( page output )
Data Status Status Status Status Status Status Status Status Status Status
Test Checked Checked Checked Checked Checked Checked Checked Checked Checked Checked
Checked is used for checkbox is checked

Use:
Request.QueryString["num"]
to get the value of num in the URL. Then iterate num times, adding a CheckBoxField to your GridView each time.

Related

How to determine which button is clicked in dynamically created DataTable

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

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

Gridview inside a repeater ondataitembound grid view rebinding

I've a repeater which has an asp gridview as following :
<asp:Repeater ID="rep" runat="server" OnItemDataBound="rep_ItemDataBound">
<ItemTemplate>
<asp:GridView ID="grdVw" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="Link" HeaderText="Link" />
</Columns>
</asp:GridView>
</ItemTemplate>
</asp:Repeater>
then on page load I bind a datatable that contains 20 rows to this repeater:
this is my page load code
protected void Page_Load(object sender, EventArgs e){
//dummy code for testing
table.Columns.Add("Name");
table.Columns.Add("Link");
DataRow row ;
for (int i = 0; i <20; i++)
{
row = table.NewRow();
row[0] = "dsadsd";
row[1] = "text";
table.Rows.Add(row);
}
for (int i = 0; i < 10; i++)
{
ds.Tables.Add(table.Copy());
}
rep.DataSource = ds;
rep.DataBind();
}
Then I handle the repeater's ItemDataBoundevent like this:
protected void rep_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item)
{
GridView grdVw = e.Item.FindControl("grdVw") as GridView;
grdVw.DataSource = table;
grdVw.DataBind();
}
}
Suprisingly the result is 20 gridviews!! I am thinking this is because ItemDataBound fires on each row in the table. So in this handler event I bind the table 20 times, but is this logically sound or am I doing something wrong?!
I could easily have a flag to make sure that the data has been bound to the table only once, but what if I've bound a dataset to the repeater? How can I handle this binding to the grid views ?
Change this line of code:
rep.DataSource = ds;
to this:
rep.DataSource = ds.Tables;
You can bind a repeater with a dataset but you need to be careful how you handle the tables inside that set.
this:
rep.DataSource = table;
rep.DataBind();
Should be:
rep.DataSource = {Some Dataset with more than one table};
rep.DataBind();
Then in your handler:
protected void rep_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item)
{
GridView grdVw = e.Item.FindControl("grdVw") as GridView;
//EDIT: my vb was showing.
grdVw.DataSource = ((DataTable)e.Item.DataItem).Rows;
grdVw.DataBind();
}
}
This is not tested but it should work with a little fiddling. What you need to know is that within the repeater you need to be referencing the dataItem of the listItem in order to get a reference to the table. Also Tables are not iEnumerable so make sure you are binding on the rows object.

Event problem inside grid view with custom paging

I want to provide custom paging in grid view.
<asp:GridView ID="gvFirst" runat="server" AutoGenerateColumns="false"
AllowPaging="true"
ondatabound="gvFirst_DataBound" >
<Columns>
<asp:BoundField DataField="ID" HeaderText="ProductID"/>
<asp:BoundField DataField="Name" HeaderText="ProductName" />
</Columns>
<PagerTemplate>
<asp:Panel ID="pnlPager" runat="server">
</asp:Panel>
</PagerTemplate>
</asp:GridView>
If I create button here and bind click event then it is fire, but problem is this event occur for each row bind with grid
protected void gvFirst_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Pager)
{
Panel pnPager = e.Row.FindControl("pnlPager") as Panel;
if (pnPager != null)
{
Button btnFirst = new Button();
btnFirst.Text = "1";
btnFirst.Click += new EventHandler(btnFirst_Click);
pnPager.Controls.Add(btnFirst);
}
}
}
If I create button here and bind click event then it is not fire; this event fire after all the rows bind to grid, so it will occur only once.
protected void gvFirst_DataBound(object sender, EventArgs e)
{
GridViewRow gvRow = gvFirst.BottomPagerRow;
if (gvRow != null)
{
Panel pnPager = gvRow.FindControl("pnlPager") as Panel;
if (pnPager != null)
{
Button btnFirst = new Button();
btnFirst.Text = "1";
btnFirst.Click += new EventHandler(btnFirst_Click);
pnPager.Controls.Add(btnFirst);
}
}
}
void btnFirst_Click(object sender, EventArgs e)
{
using (_NorthWindDataContext = new NorthWindDataContext())
{
var ProductInformation = from p in _NorthWindDataContext.Products
select new
{
ID = p.ProductID,
Name = p.ProductName
};
gvFirst.DataSource = ProductInformation.Skip(5).Take(5);
gvFirst.DataBind();
}
}
Another problem which I am facing is I want to provide custom paging. Now I have set page size to 5 and I am fetching 5 record from query so my grid pager is not display.
public class Productinformation
{
public int PID
{
get;
set;
}
public string PName
{
get;
set;
}
}
using (NorthWindDataContext _NorthWindDataContext = new NorthWindDataContext())
{
Proinfo = new List<Productinformation>();
Proinfo = (from p in _NorthWindDataContext.Products
select new Productinformation
{
PID = p.ProductID,
PName = p.ProductName,
}).ToList();
gvFirst.DataSource = Proinfo.Take(PageSize) ;
gvFirst.DataBind();
}
Proinfo variable declare globally.
Now when I bind I run this code it will give me error the data source does not support server-side data paging. If I use var type of variable then it is worked but we can't declare var type of variable globally, so I used it then I have to call this method every time in paging, and I don't want to use Objectdatasource.
GridView's RowCreated indeed will be called for every row in GridView, because that is the event where the GridView will (re)create the GridViewRows. But if you check for if (e.Row.RowType == DataControlRowType.Pager) there will be no overhead. This event is perfect for creating dynamic controls because it's called even on postback(as against RowDataBound). So your first way should be the correct one.
If you want to show the pager also when there are less than PageSize rows, you should force the pager to be visible e.g. in GridView's overridden OnPreRender.
GridViewRow pagerRow = (GridViewRow) this.BottomPagerRow;
if(pagerRow != null) pagerRow.Visible = true;

How do I disable the select button text in a gridview after clicking it once? (ASP.NET)

as the title says, How do I disable the select button text in a gridview after clicking it once? I want to click it once, then have the select cell area render an image (and the image not clickable or linking to anything).
Any ideas?
protected void Page_Load(object sender, EventArgs e)
{
dn = new holdDataContext();
if (!(Page.IsPostBack))
{
// GridView1.DataSource = dn.tennis.ToList();
// GridView1.DataBind();
GridView1.DataSource = from c in dn.tennis
orderby c.ID descending
select c;
GridView1.DataBind();
}
}
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
DataSet ds = null;
if (Session["oro"] == null)
{
ds = new DataSet();
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("Name"));
dt.Columns.Add(new DataColumn("Description"));
ds.Tables.Add(dt);
Session["oro"] = ds;
}
else
{
ds = (DataSet)Session["oro"];
}
DataRow row = ds.Tables[0].NewRow();
row["Name"] = GridView1.Rows[GridView1.SelectedIndex].Cells[2].Text;
row["Description"] = GridView1.Rows[GridView1.SelectedIndex].Cells[3].Text;
ds.Tables[0].Rows.Add(row);
}
you'll need a combination of aspx markup and code-behind:
aspx:
<asp:GridView ID="gvSample" runat="server"
DataKeyNames="CustomerID"
onselectedindexchanged="gvSample_SelectedIndexChanged">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="btnSelect" runat="server" CommandName="Select" Text="Select"></asp:LinkButton>
<asp:Image ID="imgSelect" runat="server" ImageUrl="~/imgs/whatever.jpg" Visible="false" />
</ItemTemplate>
code-behind:
protected void gvSample_SelectedIndexChanged(object sender, EventArgs e) {
LinkButton linkButton = gvSample.SelectedRow.Cells[0].FindControl("btnSelect") as LinkButton;
Image imgWhatever = gvSample.SelectedRow.Cells[0].FindControl("imgSelect") as Image;
linkButton.Enabled = false;
linkButton.Visible = false;
imgWhatever.Visible = true;
}
so, in the ItemTemplate markup of the GridView, specify the image you want to replace the Select button with but make it invisible, then disable the Select button in place of the image by swapping visibility between both objects within the event handler method gvSample_SelectedIndexChanged in the code-behind, which is what gets triggered upon clicking Select button. Since FindControl returns objects of type Control you'll have to cast to the LinkButton type of your Select button.

Resources