0

I have a gridview in a webform and I would like to know how I can select a single cell anywhere in that gridview using a mouse click.

The selected cell's background colour then changes to a specific colour and a textbox on the form displays the row number and column number which I will pass as parameters to a stored procedure.

When a subsequent cell is selected the last selected cell reverts back to it's original colour and the new cell's background colour is changed and the textbox updates to the new cell's row number and column number.

The closest I've got so far is selecting a whole row, but even this only affects the first cell of the row background-wise. The underline affects all cells in the row.

Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
    For Each row As GridViewRow In gvProgressGrid.Rows
        If row.RowType = DataControlRowType.DataRow Then
            row.Attributes("onclick") = "this.style.cursor='pointer';this.style.ine';this.style.backgroundColor ='#EEE'"
        End If
    Next

    MyBase.Render(writer)
End Sub
JDB
  • 25,172
  • 5
  • 72
  • 123
Matt
  • 263
  • 2
  • 10
  • 35
  • Do really want to postback with each cell click? This is something that should probably be handled using javascript. – JDB May 16 '13 at 15:26
  • On second thought, you'd be better off using MVC. ASP.NET is pretty terrible with client-side javascript. – JDB May 16 '13 at 15:33

3 Answers3

2

Basically: in the code behind you set an onclick script for each cell, passing the coordinates of the cell and the textbox for the results.

In the aspx the js script writes the coordinates of the clicked cell in the textbox, iterates all the cells in the table setting the color to white and finally sets the backgrond color to red only for the clicked cell

aspx code:

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="TestEvidenziazione.aspx.vb" Inherits="Web_Test_2010.TestEvidenziazione" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script type="text/javascript">
        function highlight(my_row, cell, textbox) {
            document.getElementById("<%=txtCellSelected.ClientID%>").value = my_row + ',' + cell;
            var table = document.getElementById("<%=GridView1.ClientID%>");
            for (var i = 0, row; row = table.rows[i]; i++) {
                //iterate through rows
                //rows would be accessed using the "row" variable assigned in the for loop
                for (var j = 0, col; col = row.cells[j]; j++) {
                    //iterate through columns
                    //columns would be accessed using the "col" variable assigned in the for loop
                        col.style.backgroundColor = '#ffffff';
                    if (i == my_row && j == cell) {
                        col.style.backgroundColor = '#ff0000';
                    }
                }
            }
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">

    <div>
        <asp:TextBox ID="txtCellSelected" runat="server"></asp:TextBox>
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="true" ShowHeader="false">

    </asp:GridView>
    </div>
    </form>
</body>
</html>

vb.net code:

Public Class TestEvidenziazione
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        LoadData()
    End Sub

    Private Sub LoadData()
        Dim list As New ArrayList
        Dim row1 As New myRowClass
        Dim row2 As New myRowClass
        Dim row3 As New myRowClass

        row1.a = "0,0"
        row1.b = "0,1"
        row1.c = "0,2"

        row2.a = "1,0"
        row2.b = "1,1"
        row2.c = "1,2"

        row3.a = "2,0"
        row3.b = "2,1"
        row3.c = "2,2"
        list.Add(row1)
        list.Add(row2)
        list.Add(row3)
        GridView1.DataSource = list
        GridView1.DataBind()

    End Sub

    Private Class myRowClass
        Public Property a As String
        Public Property b As String
        Public Property c As String
    End Class

    Private Sub GridView1_PreRender(sender As Object, e As System.EventArgs) Handles GridView1.PreRender
        For index_row = 0 To GridView1.Rows.Count - 1
            If GridView1.Rows(index_row).RowType = DataControlRowType.DataRow Then
                For index_cell = 0 To GridView1.Rows(index_row).Cells.Count - 1
                    GridView1.Rows(index_row).Cells(index_cell).Attributes("onclick") = "highlight(" & index_row.ToString & "," & index_cell.ToString & ", " & txtCellSelected.ClientID & "); "
                Next
            End If
        Next
    End Sub
End Class
Andrea
  • 11,801
  • 17
  • 65
  • 72
  • this is perfect and I've been able to tweak it to fit my situation. However, the background color of the cells is preset and specific to each cell. Is there a way of retrieving the original backcolour of the cell when it is clicked and changed to red so that when a new cell is clicked the cell reverts to it's original colour rather than resetting all cells to white? – Matt May 17 '13 at 11:49
2

Note: the following code is not tested. You may need to modify it to meet your needs.

In answer to your other question - reverting the cell back to its original color - you can add a custom attribute with the necessary information.

You could modify Andrea's code as follows:

Private Sub GridView1_PreRender(sender As Object, e As System.EventArgs) Handles GridView1.PreRender
    For index_row = 0 To GridView1.Rows.Count - 1
        If GridView1.Rows(index_row).RowType = DataControlRowType.DataRow Then
            For index_cell = 0 To GridView1.Rows(index_row).Cells.Count - 1
                GridView1.Rows(index_row).Cells(index_cell).Attributes("onclick") = "highlight(" & index_row.ToString & "," & index_cell.ToString & ", " & txtCellSelected.ClientID & "); "
                ' Change begins here...
                Dim l_bg = GridView1.Rows(index_row).Cells(index_cell).BackColor
                GridView1.Rows(index_row).Cells(index_cell).Attributes.Add( _
                    "data-defaultBackground", _
                    String.Format( "#{0:X2}{1:X2}{2:X2}{3:X2}", l_bg.A, l_bg.R, l_bg.G, l_bg.B )
                )
            Next
        End If
    Next
End Sub

Then switch this javascript code:

col.style.backgroundColor = '#ffffff';

to this:

col.style.backgroundColor = col.getAttribute("data-defaultBackground");

This code uses the HTML5 data attribute standard. See John Resig's blog post, HTML 5 data- Attributes, for more information. This standard is relatively new and support may be spotty.

Note that you may have some trouble with getAttributes.

I got the code for converting a Color to a hex string from an answer by VirtualBlackFox

Please consider awarding the answer/bounty to Andrea, as s/he did all the real work.

Community
  • 1
  • 1
JDB
  • 25,172
  • 5
  • 72
  • 123
  • Many thanks for the additional info. @Andrea has provided me with a solid answer that worked and I'll be able to take it forward regarding passing the grid references to a stored procedure. Your additional code is ace though and I look forward to having a go at implementing it later :) – Matt May 20 '13 at 07:34
2

I would solve this problem by using jQuery in combination with the answers given by Cyborg and Andrea. jQuery will give you more readable javascript code.

Raimond Kuipers
  • 1,146
  • 10
  • 18
  • Thanks for the tip, I'll look into this in the future once I have everything up and running and start to clean up my code. – Matt May 20 '13 at 07:36