Get dynamically created checkbox value from Gridview | Asp.net - c#

I have this gridview where I need to populate more than 25 database tables. These table are lookup table and this gridview is for lookup table maintenance purpose.
Instead of putting specific columns in gridview I directly bind the dataTable to gridview.
This below method assigns the (last column in gridview) active column's value which is "y"/"n" to checkbox.
<asp:GridView ID="gvTables" runat="server" CssClass="Grid" Width="100%" AutoGenerateColumns="true" Font-Names="Arial"
BorderWidth="1" PagerSettings-Mode="Numeric" Font-Size="8.7pt" Font-Bold="false" AlternatingRowStyle-BackColor="#f4f4f4"
HeaderStyle-BackColor="LightGray" AllowPaging="True" ShowFooter="false" PageSize="12"
OnPageIndexChanging="gvTables_PageIndexChanging"
OnRowDataBound="gvTables_RowDataBound"
OnRowCreated="gvTables_RowCreated"
OnSelectedIndexChanged="gvTables_SelectedIndexChanged">
<PagerStyle CssClass="pgr" />
</asp:GridView>
code:
private void SetCheckBoxesInGV()
{
////add checkboxes in place of active
for (int i = 0; i < gvTables.Rows.Count; i++)
{
System.Web.UI.WebControls.CheckBox chk = new System.Web.UI.WebControls.CheckBox();
chk.ID = "chk";
chk.Checked = gvTables.Rows[i].Cells[gvTables.Rows[0].Cells.Count - 1].Text.Trim() == "y" ? true : false;
gvTables.Rows[i].Cells[gvTables.Rows[0].Cells.Count - 1].Controls.Add(chk);
gvTables.Rows[i].Cells[gvTables.Rows[0].Cells.Count - 1].ControlStyle.CssClass = "ItemCenter";
}
}
So the last column looks like this instead of y/n.
Now I want to get the checkbox values, I am using this and thought it will work but it doesn't. Gives null value and "Object reference not set to an instance of an object".
((CheckBox)gvTables.Rows[i].Cells[gvTables.Rows[0].Cells.Count - 1].FindControl("chk")).Checked

So what I did was I added a template field for checkbox and used this link's help to re arrange the columns so that the checkBox column be the last column.
And then I was able to get the checkbox value easily.

Related

GridView Get the row number containing a value

I have a simple code that displays the results with a simple thank you
I just want to fetch the row number that contains a specific value, knowing that the value is unique
For example, the owner id is 3, who got 939119, falls in row number 7
enter image description here
GridView1.DataSource = dt;
dt.DefaultView.Sort = "CRPoints DESC";
GridView1.DataSource = dt.DefaultView;
GridView1.DataBind();
string idcc = GridView1.DataKeys[e.RowIndex].Values[3].ToString();
Label1.Text = idcc;
idcc = 7
Ok, I'm going to be nice today. but, I WILL state that your posted code makes ZERO sense without any context.
I would assume a typical setup is you have a GV. You load it up with data.
Then say on a row click, you want to get information about that row.
So, lets do this with a simple grid.
our GV markup is thus this:
<asp:GridView ID="GVHotels" runat="server" CssClass="table table-hover"
DataKeyNames="ID" AutoGenerateColumns="false" Width="40%" >
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="First Name" HeaderStyle-Width="100" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" HeaderStyle-Width="100" />
<asp:BoundField DataField="HotelName" HeaderText="Hotel Name" HeaderStyle-Width="120"/>
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Description" HeaderText="Province" />
<asp:TemplateField HeaderText="hotel as text box">
<ItemTemplate>
<asp:TextBox ID="txtHotel" runat="server" Text="<%# Eval("HotelName") %>" >
</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdView" runat="server" Text="Row Click" CssClass="btn"
OnClick="cmdView_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
So, two things you have to "learn" or remember:
to get a databound field from the GV, you use .Cells[] collection (starting at 0 for the first column.
to get a "control" you dropped into the GV, you have to use FindControl.
And to drop/have/use/enjoy a plain jane button or drop down, or ANY standard asp.net control in the GV, you have to "wrap" it as the above markup shows (inside of a "TemplateField", and then inside of "ItemTemplate".
So, often you just use "BoundField", but often you can (and will want to) use a standard control in the grid row.
A great example in above is the placing of a plane jane button click in the row (as per above rules).
So, we have this code to load the GV:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
string strSQL = "SELECT * FROM tblhotelsA ORDER BY HotelName";
GVHotels.DataSource = MyRst(strSQL);
GVHotels.DataBind();
}
And now we have/see this:
So, now our button click (to get the one row we click on).
this:
protected void cmdView_Click(object sender, EventArgs e)
{
Button cmdMyRowBtn = (Button)sender;
GridViewRow MyRow = (GridViewRow)cmdMyRowBtn.NamingContainer;
int PKID = (int)GVHotels.DataKeys[MyRow.RowIndex]["ID"];
Debug.Print($"Row index click = {MyRow.RowIndex.ToString()}");
Debug.Print($"Data base PK id = {PKID.ToString()}");
// get a "databound" field - use cells colleciton
Debug.Print($"Hotel name from cells field = {MyRow.Cells[2].Text}");
// get a tempatled column (those standard asp.net controls in the gv
TextBox txtHotel = (TextBox)MyRow.FindControl("txtHotel");
Debug.Print($"Hotel name from text box in gv = {txtHotel.Text}");
}
So, above, when you click, you can then do whatever you want. You can get values, take values and fill out some text boxes - do whatever.
The output from above click is this:
output:
Row index click = 1
Data base PK id = 5
Hotel name from cells field = Inns of Banff
Hotel name from text box in gv = Inns of Banff
So, from above, you should be able to do quite much anything you want.
And of course like any developer, I get VERY tired VERY fast having to type connection string and code to get a data table from sql. So I have this "handy" helper bit of code I used above.
DataTable MyRst(string strSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
cmdSQL.Connection.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
(so adjust above to use your connection string)
So above should give you the "building" block you need.
So:
To get columns from a given GV row, use .cells[] colleciton.
To get "controls" you may well use in the GV, use find control.
to get row click, see the above button code.
With these 3 things, this should allow you to do just about anything you ever want to do with a GV.
Edit: Get/find a rowindex on a column value - in this case ID
Ok, so really, we want to search/find and obtain the row index from the GV for a given value in the GV - in this case, for a given "ID" value, we want the row index.
AGAIN, context matters. Maybe this is a row click in client side JavaScript code, but as the question is written, then we looking to find the row index for a given ID.
ok, this will work:
Function GetRowIndex(sFind As String, sKey As String, GV As GridView) As Integer
For Each gRow As GridViewRow In GV.Rows
If GV.DataKeys(gRow.RowIndex).Item(sKey) = sFind Then
Return gRow.RowIndex
End If
Next
Return -1
End Function
So, there is no built in translation here.
The REAL issue, is when, where, why you want the row index based on say a given datakey. I been doing this for OVER 10 years, and have NEVER needed to do this.
In other words? DO NOT try and use the gridview as a database, or some "thing" that stores data - it is mostly for display, and if you need to search, then provide a grid search ability, and filter the results.
So, you can search values in the Grid, or values (not displayed) in datakeys.
So, this routine would return the row index for a given data key value. HOWEVER, do NOT just SHOVE general values into datakeys - in 99% of cases, datakeys is for the ONE database primary key value, and those values should NOT be exposed to the end user - they NEVER are to see the database key values - especially with web based software (too high of a security risk).
So, this routine would search datakeys:
Function GetRowIndex(sFind As String, sKey As String, GV As GridView) As Integer
For Each gRow As GridViewRow In GV.Rows
If GV.DataKeys(gRow.RowIndex).Item(sKey) = sFind Then
Return gRow.RowIndex
End If
Next
Return -1
End Function
However, if the data is in the GV, then search that, and does not "needless" add the values to the datakeys (only have/place values in datakeys that you don't want to display or expose to the end user).
So, in above, I can do this:
Dim sFindID As String
sFindID = "5"
Debug.Print($"Row index of given id {sFindID} = {GetRowIndex(sFindID, "ID", GVHotels)}")

Edit textbox of gridview cell?

I have a gridview having two columns name and address and a save button.
Its a autogenerated column grid.
<asp:GridView ID="gvStandardSummary" runat="server" HeaderStyle-CssClass="columnheaderLightBlue"
AlternatingRowStyle-CssClass="infoarea" Width="100%" AutoGenerateColumns="true"
AllowPaging="true" PageSize="20" OnPageIndexChanging="gvStandardSummary_PageIndexChanged"
OnRowDataBound="gvStandardSummary_OnRowDataBound" EmptyDataText="No work items to display."
EmptyDataRowStyle-CssClass="infoarea" OnRowCommand="gvStaffingPlan_RowCommand">
</asp:GridView>
I cannot use Item template.I need a inline edit for address column only .
when i click on address field it will become editable ...i will edit ...then click second record address edit ...and finally save it ..
On saving it should update database and Reload.I can not use item templete and have to add textbox in Rowdaabound ...but nneed the exact solution ...Any help
In Row data boung i am adding a textbox
TextBox txtAddress = new TextBox();
txtAddress.ReadOnly = false;
e.Row.Cells[1].Controls.Add(txtAddress);
e.Row.Cells[1].Style.Add("text-align", "center");
Here how can i auto fit it in cell ...and Make it editable
because i am not using Wrapping here
for (int i = 0; i < e.Row.Cells.Count; i++)
{
e.Row.Cells[i].Attributes.Add("style", "white-space:nowrap;");
}
Columns should be expand and collapse based on texts
txtpkgNumber.Text = e.Row.Cells[0].Text;
Use the EditItemTemplate Of gridview for editing
refer
http://www.aspsnippets.com/Articles/Simple-Insert-Select-Edit-Update-and-Delete-in-ASPNet-GridView-control.aspx
http://www.webcodeexpert.com/2013/07/bindsaveeditupdatecanceldeletepaging.html#.UkLRgoZi3BE
http://www.c-sharpcorner.com/UploadFile/9f0ae2/gridview-edit-delete-and-update-in-Asp-Net/

Append GridView-Columns after DataTable was databound

I have a DataTable which I have created in code file and I later bind it to a GridView which i have created by using the drag and drop feature of Visual studio.
However I have added some columns in the GridView which are not supported(correct me if I am wrong) in a DataTable, e.g Hyperlink-Column or CheckBox-Column.
I would like to build the hyperlink column and the checkbox id's with a value derived from a value generated in the DataTable from a particular column. I know I can use DataNavigateUrlfields to build dynamic links but how do I do this with a DataTable that is to be bound later?
I also need the columns in the GridView to appear after the columns in the DataTable.
Any help in the above will be highly appreciated. Any alternatives are also appreciated.
Declaratively added controls will be created first and then the databound/manually created(documented in the Page's Lifecycle, s‌​earch for "controls created declaratively"). Since you want the declarative columns last, you need a hack:
You could use RowDataBound to change the order, so that the AutoGenerated columns are followed by your other columns like Hyperlink or CheckBox columns:
protected void gridOffers_RowDataBound(object sender, GridViewRowEventArgs e)
{
TableCell cell = e.Row.Cells[0];
e.Row.Cells.RemoveAt(0);
//Move first to the end
e.Row.Cells.Add(cell);
cell = e.Row.Cells[0];
e.Row.Cells.RemoveAt(0);
//Move second to the end
e.Row.Cells.Add(cell);
}
However I have added some columns in the GridView which are not
supported(correct me if I am wrong) in a DataTable, e.g
Hyperlink-Column or CheckBox-Column.
They don't need to be supported in the DataTable but in the GridView. The table contains your data and the grid contains the view.
You can try with this code - based on RowDataBound
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server" Text=""></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
You can adjust you datbound with your event RowDataBound, i added HyperLink control, in order to customize your link as you want.
void GridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
var hyperLink = (HyperLink)e.Item.FindControl("HyperLink1");
hyperLink.NavigateUrl ="....";
var checkBox = (CheckBox)e.Item.FindControl("CheckBox1");
checkBox.Checked =....
}
}
Well there is an easy way to append a column if you are using datatable
DataTable yourDataTable = new DataTable();
Load yourDataTable by DataReader or DataAdapter
DataColumn newColumn = yourDataTable.Columns.Add("Total", typeof(Int32));
After that you can bind this datatable into your Gridview.
msdn

changing order of boundfield in gridview

i am trying to develop one application, the data displayed in Gridview. gridview contains many boundfield colums . I recently add a column after the end of last boundfield column of gridview (Imported boundfield column). so i have less chance to move the last boundfield to desired location in mark up. if i move the column to desired place, then i've to modify entire coding while row _databounding. so is there any way we can re order the columns without changing in mark up ?? ..
<asp:BoundField DataField="someData" HeaderText="SomeData"> </asp:BoundField>
<asp:CommandField UpdateText="Update" EditText="Edit" CancelText="|Cancel" ShowEditButton="true" ControlStyle-CssClass="LinkNormal" />
<asp:BoundField DataField="someData2" HeaderText="Imported"> </asp:BoundField>
out put will be like this (EDit/Delete/Imported are boundfield columns )
SomeData | Update| Imported
what i need now gridview shoud display like this
Imported | SomeData | Update
I would suggest moving away from using column indexes, and start using data keys to reference column values in the code-behind. That way, you can change the markup and move columns around without effecting the code-behind.
<asp:GridView ID="GridView1" runat="server" DataKeyNames="Col1, Col2, Col3" ... >
Using data keys, you can get column values like this in the RowDataBound event:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
string col1 = GridView1.DataKeys[e.Row.RowIndex]["Col1"].ToString();
}
It seems, that GridView hasn't such functionailty. Instead of, you can try to obtain indexes of columns in code behind by for example column's header text, below is such function that does the job:
int getColumnIndexByHeaderText(GridView gridView, string headerText)
{
for (int i = 0; i < gridView.Columns.Count; ++i)
{
if (gridView.Columns[i].HeaderText == headerText)
return i;
}
return -1;
}
And use it instead of hardcoded column indexes.

Dataset datatable formatting rows

Hi i have a dataset which contains a table retrieved from sql. It has 'product' column and 'price' column. I got the dataset and binded to grid. Now i want to make the grid's price column to be formatted to 2 decimal places(validation). Any idea please.
I should not change the select query since its an SP which gives me the dataset.
if you neither want to use Bound-Field nor change select query than as much i know you have two options left to accomplish this. First is, do value change in your dataset before binding to grid using any loop and the second option is alter values in grid on RowDataBound Event...
By altering value in Dataset:
foreach(dataRow[] dr in dataset.tables[your table index])
{
// max. two decimal places
string val = String.Format("{0:0.##}",Convert.ToDecimal(dr[column index]));
dr[column index] = val;
}
By altering value in Grid:
protected void mygrid_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
mygrid.cell[cell index].Text = String.Format("{0:0.##}",Convert.ToDecimal(dataset.tables[table index][column index][Row Index]));
}
}
Now if you want apply validation for data insert and update you can apply RegularExpressionValidator at your textBox ...
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" ErrorMessage="RegularExpressionValidator"
ControlToValidate="TextBox1" ValidationExpression="^\d{1,2}([.]\d{1})$"> ValidationGroup="MyVal"</asp:RegularExpressionValidator>
Now you have to apply
ValidationGroup="MyVal"
also on click control on which you'll perform its editing and update..
Try this:
<asp:BoundField DataField="Price" DataFormatString="{0:C2}" HeaderText="Price" />
You need to add the "DataFormatString" property to the bound field as shown above. This formats currency values to two decimal places. Check this article.
DataField refers to the name of the column in the datatable, whereas the HeaderText refers to the text which would be shown as the header of the column in grid.

Categories

Resources