To add a Serial Number as the First Column in a GridView - c#

I have a Grid View . It has two bound columns. I need to have a Serial Number column as the first column.
How can i do that ?
Thanks in Advance

<asp:TemplateField HeaderText="S No">
<ItemTemplate>
<%# Container.DataItemIndex + 1 %>
</ItemTemplate>
<ItemStyle Width="2%" />
</asp:TemplateField>

Create a datatable with two columns use a first column as autoincrement as true and AutoIncrementStep=1 like
DataTable _test = new DataTable();
DataColumn c = new DataColumn("sno", typeof(int));
c.AutoIncrement = true;
c.AutoIncrementSeed = 1;
c.AutoIncrementStep = 1;
_test.Columns.Add(c);
_test.Columns.Add("description");
gvlisting.DataSource = _test;

This is more of an adjunct answer to the OP's original question. I had a terrible time figuring out how to get the index number (serial number in the OP) of the row created by the R.Ilayaraja's answer (which worked great BTW).
In your code behind page if you want to get the index number of the row, you can use code similar to this:
Int32 idNumber = Convert.ToInt32(gvlisting.Rows[i].DataItemIndex.ToString()) + 1;
This assumes you were using an iterator 'i' to get other values from your rows, and you need to add one to the number since the index is ordinal (index 0 is the first row). If you're not using an iterator, just use .Rows[0]
I struggled mightily as an ASP.NET nugget to figure this out, so I figured I'd post this in hopes it helps some other noob like me.

Add a column called Ser and set it to ReadOnly=false.
Then add this code to your application:
if (GridSearch.Rows.Count > 1)
{
for (int i = 0; i < GridSearch.Rows.Count-1; i++)
{
GridSearch.Rows[i].Cells[0].Value = (i + 1).ToString();
}
}

Just add this code in gridview
<asp:TemplateField HeaderText="Serial No of Users">
<ItemTemplate>
<%# ((GridViewRow)Container).RowIndex + 1%>
</ItemTemplate>
<FooterTemplate>
<asp:Label ID="lbltotalall" runat="server" />
</FooterTemplate>
</asp:TemplateField>

<asp:TemplateField HeaderText="SR No">
<ItemTemplate>
<%# Container.DataItemIndex + 1 %>
</ItemTemplate>
<ItemStyle Width="5%" />
</asp:TemplateField>

use Row index a bound field or on row data bound you can add a template column on which you could use the index of the row.

Related

Add calculated column to a GridView

I have a GridView with two columns and I want to add a third column which will be column A divided by column B. I added a template field but I am getting a divide by zero error. How can I check for zero values to stop the error message?
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblCalc" runat="server" >
<%# Convert.ToDecimal(Eval("val1").ToString()) / Convert.ToDecimal(Eval("val2").ToString()) %>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
Yes, you sure can. You can even do that inline, but that would clutter your markup too much, so I would suggest moving this code to code behind.
protected decimal Calculate(string a, string b)
{
decimal ad = Convert.ToDecimal(a);
decimal bd = Convert.ToDecimal(bd);
if (bd == 0)
{
return 0; // or whatever
}
return ad / bd;
}
To call this:
<asp:Label ID="lblCalc" runat="server" >
<%# Calculate(Eval("val1").ToString(), Eval("val2").ToString()) %>
</Label>

How to get cell value in RowUpdating Event GridView?

I want to obtain the new value of a cell in the gridview rowUpdating event:
roles.RoleName = gvRoles.Rows[e.RowIndex].Cells[GetColumnIndexByName(row, "RoleName")].Text;
But the value is empty.
I have checked e.NewValues which is an ordered Dictionary. It contains the new changed value. How do I retrieve the new values for update?
aspx design is:
<asp:GridView ID="gvRoles" DataKeyNames="RoleId" runat="server"
AutoGenerateColumns="False" GridLines="Vertical" CssClass="table
table-striped table-bordered" AutoGenerateEditButton="True"
OnRowCancelingEdit="gvRoles_RowCancelingEdit" OnRowUpdating="gvRoles_RowUpdating"
OnRowEditing="gvRoles_RowEditing">
<Columns>
<asp:BoundField DataField="RoleId" HeaderText="RoleId" ReadOnly="True" />
<asp:BoundField DataField="RoleName" HeaderText="RoleName" ReadOnly="false" />
<asp:BoundField DataField="Role_Description" HeaderText="Role Description" ReadOnly="false" />
<asp:TemplateField HeaderText="RoleStatus">
<EditItemTemplate>
<asp:DropDownList ID="ddlStatus" runat="server" SelectedValue='<%# Bind("Role_Status") %>' >
<asp:ListItem>True</asp:ListItem>
<asp:ListItem>False</asp:ListItem>
</asp:DropDownList>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblRoleStatus" runat="server"
Text='<%# Bind("Role_Status") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
The easiest way which i found out is to discovered e.NewValues. As I mentioned above it is an ordered dictionary and only i need to manage it.
I need to retrieve new values from this dictionary, which is done i this way.
if (!string.IsNullOrEmpty(e.NewValues["RoleName"].ToString()))
{
roles.RoleName = e.NewValues["RoleName"].ToString();
}
if you have template field it also work for it;
if (!string.IsNullOrEmpty(e.NewValues["Role_Status"].ToString()))
{
roles.Role_Status = Convert.ToBoolean(e.NewValues["Role_Status"].ToString());
}
This is the easiest thing I ever discovered. before that i want just using Find control and casting and then retrieving all lot code.
There is also e.OldValues ordered dictionary. Every one can use it to compare the new value with old ones. If values are same they could notify user to change the value(give new cell value).
GridViewRow row = (GridViewRow)gvRoles.Rows[e.RowIndex];
TextBox textRName = (TextBox)row.Cells[1].Controls[0];
string rname=textRname.Text;
Try This:
protected void gvRoles_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
GridViewRow row = gvRoles.Rows[e.RowIndex];
TextBox txtBox= (TextBox)(row.Cells[1].Controls[0]);
if(txtBox!=null)
{
String str = txtBox.Text;
}
}
After searching long and hard I found a great article that solved my issue. Take a look at the page load if you are binding on post back then the values get updated before you are able to access them.
Follow this link for more details --> https://taditdash.wordpress.com/2014/06/30/why-gridview-rowupdating-event-is-not-giving-the-updated-values/
The return data type ICollection is a bit tricky. Would have preferred a different data type than a string array but this was simplest direct conversion.
// grabs column headers
String[] keyStrings = new string[e.NewValues.Count];
System.Collections.ICollection keys = e.NewValues.Keys;
keys.CopyTo(keyStrings, 0);
// grabs edit row values
String[] valuesStrings = new string[e.NewValues.Count];
System.Collections.ICollection values = e.NewValues.Values;
values.CopyTo(valuesStrings, 0);
The end result here has two string arrays values and keys which can then be indexed, where the column header has the same index value as the cell value of the edited row.

ASP.NET GridView Column Remove

I have a GridView with some predefined Columns and some generated in code. The idea is that I show Columns according to category, selected by user. I cannot create all Columns and just hide them because I don't know how many Columns I will need. I manage to generate Columns I needed, but the problem starts when I try to remove generated Columns. Situation looks like this:
On first load I see GridView of all categories.
After clicking in ListBox I get result I want. 1 additional Column is created (RemoveAt is not called, because no additional Columns were yet created.).
After clicking in other ListBox Item I still get result I want. Column created last time where deleted and new Column added.
At this point, if I click any other ListBox Item in LicensesCategoriesListBox_SelectedIndexChanged on debugging I see that all of GridView TemplateFields are empty (http://tinypic.com/r/98vdkm/8).
If I comment section gridView.Columns.RemoveAt(i - 1) everything works fine, just Columns keeps generating and generating. Any ideas why all of my TemplateFields, written in my Page becomes empty?
My Page looks like this:
<asp:ListBox ID="licensesCategoriesListBox" runat="server" AutoPostBack="true" OnSelectedIndexChanged="LicensesCategoriesListBox_SelectedIndexChanged" />
<asp:GridView ID="licencesGridView" runat="server" AutoGenerateColumns="False" Caption="Licencijos" DataKeyNames="id" ShowFooter="True">
<Columns>
<asp:TemplateField HeaderText="Pavadinimas">
<EditItemTemplate>
<asp:TextBox ID="licenceNameTextBox" runat="server" MaxLength="50" Text='<%# Bind("name") %>' />
</EditItemTemplate>
<FooterTemplate>
<asp:TextBox ID="newLicenceNameTextBox" runat="server" MaxLength="50" ToolTip="Pavadinimas" />
</FooterTemplate>
<ItemTemplate>
<span><%# Eval("name") %></span>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Kategorija">
<EditItemTemplate>
<asp:DropDownList ID="licenceCategoryDropDownList" runat="server" />
</EditItemTemplate>
<FooterTemplate>
<asp:DropDownList ID="newLicenceCategoryDropDownList" runat="server" ToolTip="Kategorija">
<asp:ListItem Text="Pasirinkite kategoriją:" />
</asp:DropDownList>
</FooterTemplate>
<ItemTemplate>
<span><%# Eval("category") %></span>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code:
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
FillLicences(ref licencesGridView);
}
}
protected void LicensesCategoriesListBox_SelectedIndexChanged(object sender, EventArgs e) {
FillLicences(ref licencesGridView, licensesCategoriesListBox.SelectedValue); /// Value is ID of category.
}
public void FillLicences(ref GridView gridView, string category = "") {
DataTable dataTable;
ushort categoryId;
if (UInt16.TryParse(category, out categoryId)) {
PutAdditionalColumns(ref gridView, categoryId);
dataTable = sqlCommands.GetLicences(categoryId); /// Returns DataTable [name], [category] and additional fields that I add in PutAdditionalColumns method.
} else {
dataTable = sqlCommands.GetAllLicences(); /// Returns DataTable with only [name], [category]
}
gridView.DataSource = dataTable;
gridView.DataBind();
}
public void PutAdditionalColumns(ref GridView gridView, uint category) {
for (ushort i = (ushort)gridView.Columns.Count; i > 2; i--) { /// Removes columns at the end (created for other category)
gridView.Columns.RemoveAt(i - 1);
}
foreach (var pair in sqlCommands.GetLicencesCategoryAttributes(category)) { /// Takes additional field needed.
TemplateField field = new TemplateField(); /// New empty column.
field.AccessibleHeaderText = pair.Key.ToString();
field.HeaderText = pair.Value;
gridView.Columns.Add(field);
}
}
Any ideas why all of my TemplateFields, written in my Page becomes
empty?
Because each of those fields is considered a Column. You're removing them in the code.
If this is your issue, you need some way to seperate columns defined in the aspx to the ones created in the code.
I'd use DataColumn.ExtendedProperties to do this.
Whenever you add a column from code, add a value to ExtendedProperties, showing that it was created in the code.
//...
TemplateField field = new TemplateField(); /// New empty column.
field.AccessibleHeaderText = pair.Key.ToString();
field.HeaderText = pair.Value;
DataColumn ourNewColumn = gridView.Columns.Add(field);
ourNewColumn.ExtendedProperties.Add("CreatedInCode", true);
//...
And then when you come to delete them, only delete them if they have this property set.
//...
if( gridView.Columns[i - 1].ExtendedProperties.ContainsKey("CreatedInCode") ) {
gridView.Columns.RemoveAt(i - 1);
}
//...

How to trim the column in gridview

i have a gridview, the column has 20 records whose values are in decimal.say like 5686252.345656 i want to trim those value. So that i could see 5686252.34. It would be great if i trim it in the c# code rather in SQL.
Ive binded the values like this..
<asp:TemplateField HeaderText="Weighted Avg" SortExpression="WT_AVG"
ItemStyle-HorizontalAlign="Center" HeaderStyle-VerticalAlign="Top" HeaderStyle-Width="70px">
<ItemTemplate>
<asp:Label ID="lblWT" runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"WT_AVG") %>' />
</ItemTemplate>
</asp:TemplateField>
Please help me.
Thanks.
You can apply a format string to the binding statement:
Example:
<%# DataBinder.Eval(Container.DataItem, "Price", "{0:c}") %>
I would use Math.Round(decimal d,int decimals) for example
Math.Round(3.44, 1); //Returns 3.4.
Math.Round(3.45, 1); //Returns 3.4.
Math.Round(3.46, 1); //Returns 3.5.
Math.Round(4.34, 1); // Returns 4.3
Math.Round(4.35, 1); // Returns 4.4
Math.Round(4.36, 1); // Returns 4.4
http://msdn.microsoft.com/en-us/library/zy06z30k(v=vs.100).aspx
EDIT: OR do it in the SQL:
SELECT ROUND(123.9994,3), ROUND(123.9995,3)
returns: 123.9990 124.0000
Rounding on MSDN

How do I set the GridView RowHeaderColumn to a TemplateField?

I have a standard ASP.NET GridView and I'd like the first column (a emplateField) to be rendered as <th>, or in ASP.NET terms, I'd like to set it to the GridView RowHeaderColumn property. But that property is looking for the name of a DataItem (from a BoundColumn).
How can I render my TemplateField with <th> tags?
Finally found a workaround for this. I am not sure if this code has anything to do with good ASP.NET practices, but it does the trick:
public class FirstColumnHeaderGridView : GridView
{
protected override void InitializeRow(GridViewRow row, DataControlField[] fields)
{
DataControlFieldCell cell = new DataControlFieldHeaderCell(fields[0]);
DataControlCellType header = DataControlCellType.DataCell;
fields[0].InitializeCell(cell, header, row.RowState, row.RowIndex);
row.Cells.Add(cell);
DataControlField[] newFields = new DataControlField[fields.Length - 1];
for (int i = 1; i < fields.Length; i++)
{
newFields[i - 1] = fields[i];
}
base.InitializeRow(row, newFields);
}
}
Let me explain what is going on here. We are creating a special type of GridView, that will render its first column using <th> tags no matter how this column is created. For this we are overriding the InitializeRow method. This method basically configures cells for the row. We are handling the first cell, and let standard GridView take care of the rest.
The configuration we are applying to the cell is fully taken from the GridView implementation and is enough for the cell to be rendered with <th> tag instead of <td>.
After that workaround the usage is absolutely standard - register our class as a server control and use it as usual GridView:
<%# Register Assembly="WebApplication1" Namespace="WebApplication1" TagPrefix="wa1" %>
...
<wa1:FirstColumnHeaderGridView ID="Grid1" runat="server" ...>
<Columns>
<asp:TemplateField>
<ItemTemplate>
Will be inside th
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
Will be inside td
</ItemTemplate>
</asp:TemplateField>
</Columns>
</wa1:FirstColumnHeaderGridView>
Is this what you mean?
<Columns>
<asp:TemplateField HeaderText="Código" ItemStyle-Width="9%">
<HeaderTemplate>
<asp:Label runat="server" Text="CodigoSAP"></asp:Label>
</HeaderTemplate>
<ItemTemplate>
<asp:Label runat="server" ID="lblCodigoSAP" Text='<%# Bind("CodigoSAP") %>'> </asp:Label>
</ItemTemplate>
</asp:TemplateField>
I'm almost sure I'm getting the wrong idea, what do you say?
Late to the game, but we needed to set scope="row" in a middle column, not the first. To make it generic, in a derived GridView class I added the following property (similar to the GridView's built-in RowHeaderColumn property):
public int? RowHeaderColumnIndex
{
get { return (int?)ViewState["RowHeaderColumnIndex"]; }
set { ViewState["RowHeaderColumnIndex"] = value; }
}
Then set the scope:
protected override void OnRowCreated(GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow && RowHeaderColumnIndex.HasValue)
{
e.Row.Cells[RowHeaderColumnIndex.Value].Attributes["scope"] = "row";
}
}
When you place your custom grid just set RowHeaderColumnIndex="0" for the first column, "1" for the 2nd column and so on.

Categories

Resources