1

First of I don't know if this is possible, the correct way to go or even will work, but I hope you guys can help me out, I will try to explain:

I have a GridView Control on the ASPX page:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="True" OnRowDataBound="GridView1_RowDataBound" GridLines="None" CssClass="table table-striped" />

I created a DataTable in the code-behind which holds the following data and have bind it to the Gridview control:

-----------------------------------------
|       | Name1 | Name2 | Name3 | Name4 |
-----------------------------------------
| Row1  | 1     | 1     | 1     | 1b    |
| Row2  | 1a    | 2b    | 2b    | 4b    |
| Row3  | 2a    | 2c    | 2a    | 2a    |
| Row4  | 1d    | 1d    | 1d    | 4d    |
| Row5  | 1e    | 1e    | 1e    | 1e    |
| Row6  | 1f    | 2f    | 3f    | 4f    |
-----------------------------------------

Now I would like matching column values to be merged and add the appropriate colspan. I have added to the GridView control a OnRowDataBound as following:

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        if (e.Row.RowIndex >= 0)
        {
            int colSpanValue = 2;
            for (int i = 0; i < e.Row.Cells.Count; i++)
            {
                if (i+1 < e.Row.Cells.Count) 
                {
                    if (e.Row.Cells[i].Text == e.Row.Cells[i + 1].Text)
                    {
                        e.Row.Cells[i].BackColor = Color.Beige;
                        e.Row.Cells[i].ColumnSpan = colSpanValue;
                        e.Row.Cells[i].HorizontalAlign = HorizontalAlign.Center;
                        e.Row.Cells[i + 1].Visible = false;
                        colSpanValue++;
                    }
                }
            }
        }
    }
}

so the above data would like this, something like this.

-----------------------------------------
|       | Name1 | Name2 | Name3 | Name4 |
-----------------------------------------
| Row1  |       1       | 1b            | <!-- problem
| Row2  | 1a    |      2b       | 4b    |
| Row3  | 2a    | 2c    |      2a       | <!-- problem
| Row4  |           1d          | 4d    |
| Row5  |              1e               |
| Row6  | 1f    | 2f    | 3f    | 4f    |
-----------------------------------------

Currently I managed to get this, see screenshot enter image description here

However this is not really what i would like to see, but would expect as the OnRowDataBound code block is probably not done the right.

So my question is:

  • How could I merge all equal columns in a row and add colspan to them?
  • Now for the tricky bit, would I be able to sort the columns so, that matching column cells are displayed properly? (not sure about this)

So the ideal result would be like this:

-----------------------------------------
|       | Name1 | Name2 | Name3 | Name4 |
-----------------------------------------
| Row1  |           1           | 1b    | <!-- problem
| Row2  | 1a    |      2b       | 4b    |
| Row3  | 2a    | 2c    |      2a       | <!-- problem
| Row4  |           1d          | 4d    |
| Row5  |              1e               |
| Row6  | 1f    | 2f    | 3f    | 4f    |
-----------------------------------------

UPDATED INFORMATION

After updating the code according to the answers provided by ConnorsFan and fnostro, both answers are correct and work, thank you for the help. I choose for ConnorsFan's approach, as i'm still learning.

The collspan's are now correct, see screenshot below:

enter image description here

I will try to fnostro's advise to manage the sorting part via the DataTable and rebind the data to the GridView1 and keep you posted. once again thank you for your answers.

2 Answers 2

2

You can try this:

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        for (int i = 0; i < e.Row.Cells.Count - 1; i++)
        {
            TableCell cell = e.Row.Cells[i];

            if (cell.Visible)
            {
                int colSpanValue = 1;

                for (int j = i + 1; j < e.Row.Cells.Count; j++)
                {
                    TableCell otherCell = e.Row.Cells[j];

                    if (otherCell.Text == cell.Text)
                    {
                        colSpanValue++;
                        otherCell.Visible = false;
                    }
                    else
                    {
                        break;
                    }
                }

                if (colSpanValue > 1)
                {
                    cell.ColumnSpan = colSpanValue;
                    cell.BackColor = Color.Beige;
                    cell.HorizontalAlign = HorizontalAlign.Center;
                }
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much, this works great, I have added updated information including a screenshot with the result of your answer.
0

Regarding sorting. It's better to manage sorting in the DataTable and simply rebind to the GridView

Here is how I modified the RowDataBound Event to merge like data:

    protected void GridView1_RowDataBound( object sender, GridViewRowEventArgs e ) 
    {
      if ( e.Row.RowType == DataControlRowType.DataRow ) 
      {
        // loop through cells and track span index (si)
        for ( int i = 0, si = 0; i < e.Row.Cells.Count; si = i) 
        {
          // compare adjacent cells for like data and hide as needed
          while ( ++i < e.Row.Cells.Count && e.Row.Cells[ si ].Text == e.Row.Cells[ i ].Text )
            e.Row.Cells[ i ].Visible = false;

          // set span and, conditionally, special formatting
          if ( ( e.Row.Cells[ si ].ColumnSpan = ( i - si ) ) > 1 ) 
          {
            e.Row.Cells[ si ].BackColor = Color.Beige;
            e.Row.Cells[ si ].HorizontalAlign = HorizontalAlign.Center;
          }
        }
      }
    }

7 Comments

Thank you for your advise regarding the sorting of the columns, I will look how i could achieve this.
Glad to help. Look into Linq. See this SO question
This allows me to sort by the values within a columns (top to bottom) however would there be a way to sort the rows, e.g: left to right on row level, if you take a look at my updated information and check row 3, you will see the following result: ( 2a, 2b, 2x2a ) Now ideally i would like to group these together, but not sure if this would be the correct approach as it would involve shifting the whole column, but i could imagine that if we sort the first row correctly, and go to the second row, we might mess up the first row result again, not sure if this is going to work.
Group how? such that you have (3x2a, 2c)? Sorting by row is going to be a chore because typically data tables are sorted by column. You can roll your own sort procedure that sorts by row. Or your can "pivot" the data table and sort normally. I don't know what you are trying to accomplish overall. Are you trying to sort first by column then by row before grouping? Or some combination of Col sort, group, row sort, regroup???
HI fnostro, As you said: such that you have (3x2a, 2c)? Indeed, however I might need to open another question for this issue, as you mentioned and I already discovered, it seem to be a chore to sort by row, and indeed have noticed that everything is in place to sort by columns, however rows is a different matter and totally understandable, this is why i think a gridview control with datatable might not be the ideal solution for my requirements, The idea behind it is to display the shared values next to each other and merged so you can see which columns shared the same row data value. thanks
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.