Vara Prasad.M
Vara Prasad.M

Reputation: 1550

How to get the cell value by column name not by index in GridView in asp.net

I am having a gridview in asp.net and now I want the cell value by the column name but not by the cell index.

How would be it possible by retrieving the cell value by the cell column name

Upvotes: 48

Views: 141111

Answers (13)

diehlmitchell
diehlmitchell

Reputation: 11

The primary reason this would be difficult is because gridview cells do not have accessible cell names (ugh).

In order to work around this handicap you can make an extension method (mine is in VB.NET, but @Дмитрийh seems to have a similar solution in C#).

To work around this ensure the HeaderText of the gridview cells have the same value as the cellnames and grab the values via that HeaderText name.

Here is extension methods you would need for strings and integers in a VB.NET code snippet that I made

Public Shared Function GetStringByCellName(pGridViewRow As GridViewRow, pCellName As String) As String
    For Each myCell As DataControlFieldCell In pGridViewRow.Cells
        If myCell.ContainingField.ToString() = pCellName Then
            Return myCell.Text
        End If
    Next
    Return Nothing
End Function

And the difference for integers being a parse/cast

Public Shared Function GetIntegerByCellName(pGridViewRow As GridViewRow, pCellName As String) As Integer
        For Each myCell As DataControlFieldCell In pGridViewRow.Cells
            If myCell.ContainingField.ToString() = pCellName Then
                Return Integer.Parse(myCell.Text)
            End If
        Next
    Return Nothing
End Function

And calling the functions would look like this if it were in a class.

Dim columnNamesStringValue As String = ExtensionMethodsClassName.GetStringByCellName(pGridViewRow, "stringOfColumnName")

Dim columnNamesIntegerValue As Integer = ExtensionMethodsClassName.GetIntegerByCellName(pGridViewRow, "stringOfColumnName")

have in mind that you may not always get a value, and instead may get Nothing

Before you (perhaps try to put the value in your database), ensure it is not nothing first by checking that it is not nothing. If you wanted to insert into the database, however, it may be better to return a System.DBNull instead of Nothing from the extension methods I provided. (DO NOT CHECK AND INSERT THE OTHER NULLS or Nothing AS DBNull'S. DIFFERENT TYPES OF NULL'S AND NOTHINGS ARE NOT EQUAL)

If (columnNamesStringValue IsNot Nothing) 

Upvotes: 0

Дмитрий
Дмитрий

Reputation: 294

protected void gvResults_PreRender(object sender, EventArgs e)
{
    var gridView = (GridView)sender;
    gridView.GetColumnByName("YourDataBoundDataField").Visible = true;
}

Extension:

    public static DataControlField GetColumnByName(this GridView gridView, string columnName)
    {
        int columnIndex = -1;
        for (int i = 0; i < gridView.Columns.Count; i++)
        {
            if (gridView.Columns[i].HeaderText.Trim().Equals(columnName, StringComparison.OrdinalIgnoreCase))
            {
                columnIndex = i;
                break;
            }
        }

        if (columnIndex == -1)
        {
            throw new ArgumentOutOfRangeException("GridViewRow does not have the column with name: " + columnName);
        }

        return gridView.Columns[columnIndex];
    }

Upvotes: 0

gpemp
gpemp

Reputation: 11

We can get it done in one line of code. No need to loop through anything or call other methods.

protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        string cellValue = e.Row.Cells[e.Row.Cells.GetCellIndex(e.Row.Cells.Cast<DataControlFieldCell>().FirstOrDefault(cell => cell.ContainingField.HeaderText == "columnName"))].Text;
    }
}

Upvotes: 1

Mohan
Mohan

Reputation: 43

Header Row cells sometimes will not work. This will just return the column Index. It will help in a lot of different ways. I know this is not the answer he is requesting. But this will help for a lot people.

public static int GetColumnIndexByHeaderText(GridView gridView, string columnName)
    {      
        for (int i = 0; i < gridView.Columns.Count ; i++)
        {
            if (gridView.Columns[i].HeaderText.ToUpper() == columnName.ToUpper() )
            {
                return i;
            }
        }     
        return -1;
    }

Upvotes: 2

user13582603
user13582603

Reputation: 1

protected void CheckedRecords(object sender, EventArgs e)

    {
       string email = string.Empty;
        foreach (GridViewRow gridrows in GridView1.Rows)

        {

            CheckBox chkbox = (CheckBox)gridrows.FindControl("ChkRecords");
    if (chkbox != null & chkbox.Checked)

            {

    int columnIndex = 0;
                foreach (DataControlFieldCell cell in gridrows.Cells)
                {
                    if (cell.ContainingField is BoundField)
                        if (((BoundField)cell.ContainingField).DataField.Equals("UserEmail"))
                            break;
                    columnIndex++; 
                }


                email += gridrows.Cells[columnIndex].Text + ',';
                  }

        }

        Label1.Text = "email:" + email;

    }                           

Upvotes: 0

Zeek2
Zeek2

Reputation: 426

It is possible to use the data field name, if not the title so easily, which solved the problem for me. For ASP.NET & VB:

e.g. For a string:

Dim Encoding = e.Row.DataItem("Encoding").ToString().Trim()

e.g. For an integer:

Dim MsgParts = Convert.ToInt32(e.Row.DataItem("CalculatedMessageParts").ToString())

Upvotes: 0

dizad87
dizad87

Reputation: 468

//get the value of a gridview
public string getUpdatingGridviewValue(GridView gridviewEntry, string fieldEntry)
    {//start getGridviewValue
        //scan gridview for cell value
            string result = Convert.ToString(functionsOther.getCurrentTime()); 
            for(int i = 0; i < gridviewEntry.HeaderRow.Cells.Count; i++)
                {//start i for
                    if(gridviewEntry.HeaderRow.Cells[i].Text == fieldEntry)
                        {//start check field match
                            result = gridviewEntry.Rows[rowUpdateIndex].Cells[i].Text;
                            break;
                        }//end check field match
                }//end i for
        //return
            return result;
    }//end getGridviewValue

Upvotes: 0

Galactic
Galactic

Reputation: 416

Based on something found on Code Project

Once the data table is declared based on the grid's data source, lookup the column index by column name from the columns collection. At this point, use the index as needed to obtain information from or to format the cell.

protected void gridMyGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        DataTable dt = (DataTable)((GridView)sender).DataSource;
        int colIndex = dt.Columns["MyColumnName"].Ordinal;

        e.Row.Cells[colIndex].BackColor = Color.FromName("#ffeb9c");
    }
}

Upvotes: 2

bruno leclerc
bruno leclerc

Reputation: 342

A little bug with indexcolumn in alexander's answer: We need to take care of "not found" column:

int GetColumnIndexByName(GridViewRow row, string columnName)
{
    int columnIndex = 0;
    int foundIndex=-1;
    foreach (DataControlFieldCell cell in row.Cells)
    {
        if (cell.ContainingField is BoundField)
        {
            if (((BoundField)cell.ContainingField).DataField.Equals(columnName))
            {
                foundIndex=columnIndex;
                break;
            }
        }
        columnIndex++; // keep adding 1 while we don't have the correct name
    }
    return foundIndex;
}

and

protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        int index = GetColumnIndexByName(e.Row, "myDataField");
        if( index>0)
        {
            string columnValue = e.Row.Cells[index].Text;
        }
    }
}

Upvotes: 1

Circle Hsiao
Circle Hsiao

Reputation: 1977

For Lambda lovers

protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        var boundFields = e.Row.Cells.Cast<DataControlFieldCell>()
            .Select(cell => cell.ContainingField).Cast<BoundField>().ToList();

        int idx = boundFields.IndexOf(
            boundFields.FirstOrDefault(f => f.DataField == "ColName"));

        e.Row.Cells[idx].Text = modification;        
    }
}

Upvotes: 2

Daniel Nutu
Daniel Nutu

Reputation: 56

You can use the DataRowView to get the column index.

    void OnRequestsGridRowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            var data = e.Row.DataItem as DataRowView;

            // replace request name with a link
            if (data.DataView.Table.Columns["Request Name"] != null)
            {
                // get the request name
                string title = data["Request Name"].ToString();
                // get the column index
                int idx = data.Row.Table.Columns["Request Name"].Ordinal;

                // ...

                e.Row.Cells[idx].Controls.Clear();
                e.Row.Cells[idx].Controls.Add(link);
            }
        }
    }

Upvotes: 3

Sadiq
Sadiq

Reputation: 838

Although its a long time but this relatively small piece of code seems easy to read and get:

protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
   int index;
   string cellContent;

    foreach (TableCell tc in ((GridView)sender).HeaderRow.Cells)
    {
       if( tc.Text.Equals("yourColumnName") )
       {
         index = ((GridView)sender).HeaderRow.Cells.GetCellIndex(tc);
         cellContent = ((GridView)sender).SelectedRow.Cells[index].Text;
         break;
       }
    }
}

Upvotes: 4

balexandre
balexandre

Reputation: 75073

GridView does not act as column names, as that's it's datasource property to know those things.

If you still need to know the index given a column name, then you can create a helper method to do this as the gridview Header normally contains this information.

int GetColumnIndexByName(GridViewRow row, string columnName)
{
    int columnIndex = 0;
    foreach (DataControlFieldCell cell in row.Cells)
    {
        if (cell.ContainingField is BoundField)
            if (((BoundField)cell.ContainingField).DataField.Equals(columnName))
                break;
        columnIndex++; // keep adding 1 while we don't have the correct name
    }
    return columnIndex;
}

remember that the code above will use a BoundField... then use it like:

protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        int index = GetColumnIndexByName(e.Row, "myDataField");
        string columnValue = e.Row.Cells[index].Text;
    }
}

I would strongly suggest that you use the TemplateField to have your own controls, then it's easier to grab those controls like:

<asp:GridView ID="gv" runat="server">
    <Columns>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:Label ID="lblName" runat="server" Text='<%# Eval("Name") %>' />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

and then use

string columnValue = ((Label)e.Row.FindControl("lblName")).Text;

Upvotes: 78

Related Questions