This one was asked at Forums. I quickly created a small helper class which can be extended at will, in case one wants to access also the other field types. However, I wrote class GridViewBoundFieldHelper as follows:
public class GridViewBoundFieldHelper
{
public static int GetIndex(GridView grd,string fieldName)
{
for (int i = 0; i < grd.Columns.Count; i++)
{
DataControlField field = grd.Columns[i];
BoundField bfield = field as BoundField;
//Assuming accessing happens at data level, e.g with data field's name
if (bfield != null && bfield.DataField == fieldName)
return i;
}
return -1;
}
public static BoundField GetField(GridView grd, string fieldName)
{
int index = GetIndex(grd,fieldName);
return (index==-1)? null : grd.Columns[index] as BoundField ;
}
public static string GetText(GridViewRow row, string fieldName)
{
GridView grd = row.NamingContainer as GridView;
if (grd != null)
{
int index = GetIndex(grd, fieldName);
if(index != -1)
return row.Cells[index].Text;
}
return "";
}
}
Trick is that it looks specifically for BoundField and compares the given field name to field's DataField name. One could extend this, and perhaps improve the comparison, my point was just to demonstrate creating a small helper. One thing to improve immediately would be implementing some sort of caching so that field indexes would be resolved only once, and for the next access, they'd be looked from cache or something.
Usage example with Orders table (found in Northwind database). I post all the relevant code.
CustomersDAL.cs
public static DataTable GetCustomersOrders(string customerId)
{
using (SqlConnection conn = new SqlConnection(Configuration.ConnectionString))
{
SqlCommand cmd = new SqlCommand("dbo.CustOrdersOrders", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@CustomerID", SqlDbType.NChar, 5).Value = customerId;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
}
Then the GridView declaration and data-binding
<asp:GridView ID="grdOrders" runat="server" AutoGenerateColumns="false" DataKeyNames="OrderID" OnRowDataBound="grdOrders_RowDataBound">
<Columns>
<asp:BoundField DataField="OrderID" HeaderText="Order ID" />
<asp:BoundField DataField="OrderDate" HeaderText="Order Date" HtmlEncode="false" DataFormatString="{0:dd.MM.yyyy}" />
<asp:BoundField DataField="RequiredDate" HeaderText="Required Date" HtmlEncode="false" DataFormatString="{0:dd.MM.yyyy}" />
<asp:BoundField DataField="ShippedDate" HeaderText="Shipped Date" HtmlEncode="false" DataFormatString="{0:dd.MM.yyyy}" />
</Columns>
</asp:GridView>
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
grdOrders.DataSource = CustomerDAL.GetCustomersOrders("ALFKI");
grdOrders.DataBind();
}
}
Then the real usage of the helper class written listed at the beginning, in RowDataBound. We look for the value of "OrderDate" BoundField
protected void grdOrders_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string text = GridViewBoundFieldHelper.GetText(e.Row, "OrderDate");
//Do something with the Text
//Output to test it
Response.Write(text + "<br>");
}
}
As you can see, it isn't that difficult to implement. And it can be extended easily to cover other field types, and perhaps to look for a specific row for example
public static string GetText(GridView grd, int rowIndex,string fieldName)
{
GridViewRow row = grd.Rows[rowIndex];
return GetText(row, fieldName);
}
It's up to you totally what it can be extended to do.
Hope this helps,
Share this post: email it! | bookmark it! | digg it! | reddit! | kick it! | live it!