Cómo combinar datosGridView Cells basado en el mismo id (Column 0)

Estoy buscando fusionar células a través de un número de columnas donde el id en la columna 0 es el mismo.
Un ejemplo de DataGridView antes de las células fusionadas es:

enter image description here

La salida que estoy buscando es:

enter image description here

En este ejemplo estoy buscando células de fusión en las columnas 0,1 y 2 donde el Id es el mismo.
He estado buscando utilizar el código encontrado en lo siguiente Ejemplo de código pero no puede conseguir que produzca los resultados que necesito.
Cualquier asistencia sería apreciada.

Actualización

Me las arreglé para conseguir una versión de trabajo, pero el lado inferior es cada vez que pernomino el DataGridView con un conjunto de datos mucho más grande que los ejemplos anteriores que repinta las células como una mezcla entre la salida original y necesaria.

Mi código es

int _rowIndex = 0;
    public bool IsColumnZeroSameValue(int column, int row)
    {
        if (column > 0)
        {
            return false;
        }
        if (dgvData[column, row].Value.ToString() == dgvData[column, row - 1].Value.ToString())
        {
            _rowIndex = row;
            return true;
        }
        return false;
    }

    private void dgvData_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        if (e.RowIndex == 0)
            return;
        IsColumnZeroSameValue(e.ColumnIndex, e.RowIndex);
        if (e.RowIndex ==_rowIndex & e.ColumnIndex<2)
        {
            e.Value = "";
            e.FormattingApplied = true;
        }
    }

    private void dgvData_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
        e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None;
        if (e.RowIndex < 1 || e.ColumnIndex < 0)
            return;
        if (e.RowIndex == _rowIndex & e.ColumnIndex < 2)
        {
            e.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None;
        }
        else
        {
            e.AdvancedBorderStyle.Top = dgvData.AdvancedCellBorderStyle.Top;
        }
    }

Cualquier idea sobre cómo resolver esta cuestión sería muy apreciada.

Pregunta hecha hace 3 años, 4 meses, 29 días - Por debugdragon


3 Respuestas:

  • Usted podría modificar IsColumnsZeroSameValue para validar basado en una columna fija y no en la columna de pintura, ver la imagen adjunta.

    Formato de las filas agrupadas de datagrid

    Respondida el Dec 18, 2020 a las 10:31 - por devninjax

    Votos positivos: 0 | Votos negativos: 0

  • Para lograr fusionar las celdas basadas en el mismo Id en la columna 0 de un DataGridView, primero debes asegurarte de que los datos estén ordenados por ese Id. Luego, puedes utilizar el evento CellFormatting para modificar visualmente las celdas y el evento CellPainting para ajustar las bordes de las celdas fusionadas.

    Aquí te dejo un ejemplo de código que puedes probar:

    csharp
    int _previousId = -1;
    int _mergeStart = 0;
    
    private void dgvData_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        if (e.ColumnIndex == 0)
        {
            int currentId = (int)dgvData.Rows[e.RowIndex].Cells[0].Value;
    
            if (currentId == _previousId)
            {
                if (_mergeStart == -1)
                {
                    _mergeStart = e.RowIndex - 1;
                }
                else if (e.RowIndex == dgvData.Rows.Count - 1)
                {
                    dgvData.Rows[e.RowIndex].Cells[0].Value = "";
                    for (int i = 1; i <= 2; i++)
                    {
                        dgvData.Rows[e.RowIndex].Cells[i].Value = "";
                    }
                    dgvData.Rows[e.RowIndex].Cells[0].OwningRow.Height = dgvData.Rows[_mergeStart].Height;
                }
            }
            else
            {
                if (_mergeStart != -1 && e.RowIndex - _mergeStart > 1)
                    dgvData.Rows[_mergeStart].Cells[0].OwningRow.Height = dgvData.Rows[_mergeStart].Height * (e.RowIndex - _mergeStart);
                _mergeStart = -1;
            }
    
            _previousId = currentId;
        }
    }
    
    private void dgvData_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
        if (e.RowIndex == _mergeStart && e.ColumnIndex < 3)
        {
            e.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None;    
        }
        else
        {
            e.AdvancedBorderStyle.Top = dgvData.AdvancedCellBorderStyle.Top;
        }
    }
    

    En este código, se utiliza la variable _previousId para realizar un seguimiento del Id anterior y _mergeStart para marcar el inicio de la fusión de celdas. Se identifican las celdas que deben fusionarse y se ajustan visualmente utilizando los eventos CellFormatting y CellPainting.

    Por favor, inténtalo y hazme saber si necesitas más ayuda o aclaraciones.

    Respondida el Dec 19, 2020 a las 10:29 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Solución para combinar celdas basadas en el mismo ID

    Para combinar celdas en un DataGridView en función del mismo valor de ID en la columna 0, puedes utilizar el siguiente código:

    
    private void dgvData_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
        // Solo procesa las celdas que no están en la primera fila o columna
        if (e.RowIndex == 0 || e.ColumnIndex == 0)
            return;
    
        // Obtiene el valor de la celda actual y de la celda anterior en la columna 0
        object currentValue = dgvData[0, e.RowIndex].Value;
        object previousValue = dgvData[0, e.RowIndex - 1].Value;
    
        // Si el valor actual es igual al valor anterior, combina las celdas
        if (currentValue.ToString() == previousValue.ToString())
        {
            // Establece el valor de la celda actual como vacío para ocultarla
            e.Value = "";
    
            // Establece el estilo de borde de la celda anterior para eliminar el borde inferior
            dgvData[0, e.RowIndex - 1].Style.BorderBottom = DataGridViewBorder.None;
    
            // Establece el estilo de borde de la celda actual para eliminar el borde superior
            e.CellStyle.BorderTop = DataGridViewBorder.None;
        }
    }
    

    Solución para el problema de repintado

    Para resolver el problema de repintado, puedes agregar un indicador para verificar si el DataGridView está siendo repintado:

    
    private bool _isRepainting = false;
    

    En el evento CellFormatting, puedes establecer _isRepainting en true antes de realizar cualquier cambio:

    
    private void dgvData_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        _isRepainting = true;
    
        // Tu código de formato existente...
    }
    

    En el evento CellPainting, puedes verificar _isRepainting y omitir el código de fusión si es true:

    
    private void dgvData_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
        // Solo procesa las celdas si no se está repintando
        if (_isRepainting)
            return;
    
        // Tu código de fusión existente...
    }
    

    Después de procesar las celdas, puedes restablecer _isRepainting a false:

    
    private void dgvData_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
        // ... Tu código de fusión...
        _isRepainting = false;
    }
    

    Estos cambios deberían resolver los problemas de repintado y fusión de celdas en tu DataGridView.

    Respondida el Dec 19, 2020 a las 10:40 - por Gemini

    Votos positivos: 0 | Votos negativos: 0