Skip to content

This example describes how to merge the cells based on its content and value of a specific column in WinUI DataGrid.

Notifications You must be signed in to change notification settings

SyncfusionExamples/How-to-merge-the-cells-based-on-its-content-and-value-of-a-specific-column-in-WinUI-DataGrid

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

How to merge the cells based on its content and value of a specific column in WinUI DataGrid?

About the sample

This example describes how to merge the cells based on its content and value of a specific column in WinUI DataGrid.

WinUI DataGrid (SfDataGrid) allows to merge the cells based on the content and value of a specific column in the same row by customizing the GetRange method and QueryCoveredRange event in DataGrid.

this.sfDataGrid.ItemsSourceChanged += OnItemsSourceChanged;
this.sfDataGrid.QueryCoveredRange += OnQueryCoveredRange;

/// <summary>
/// Reflector for SfDataGrid’s data.
/// </summary>
IPropertyAccessProvider reflector = null;

/// <summary>
/// ItemsSourceChanged event handler.
/// </summary>
private void OnItemsSourceChanged(object sender, GridItemsSourceChangedEventArgs e)
{
            if (sfDataGrid.View != null)
                reflector = sfDataGrid.View.GetPropertyAccessProvider();
            else
                reflector = null;
}

/// <summary>
/// QueryCoveredRange event handler
/// </summary>
private void OnQueryCoveredRange(object sender, GridQueryCoveredRangeEventArgs e)
{
            CoveredCellInfo range = null;

            ////here apply merge the cell based on Columns
            if (e.GridColumn.MappingName == "Product" || e.GridColumn.MappingName == "Country" )
                range = GetRange(e.GridColumn, e.RowColumnIndex.RowIndex, e.RowColumnIndex.ColumnIndex, e.Record);

            if (range == null)
                return;

            // You can know that the range is already exist in Covered Cells by IsInRange method.
            if (!sfDataGrid.CoveredCells.IsInRange(range))
            {
                e.Range = range;
                e.Handled = true;
            }

            //If the calculated range is already exist in CoveredCells, you can get the range using SfDataGrid.GetConflictRange (CoveredCellInfo coveredCellInfo) extension method.
}

/// <summary>
/// Method to get the covered range based on cell value.
/// </summary>
/// <param name="column"></param>
/// <param name="rowIndex"></param>
/// <param name="columnIndex"></param>
/// <param name="rowData"></param>
/// <returns> Compares the adjacent cell value and returns the range </returns>
/// <remark> If the method find that the adjacent values are equal by horizontal then it will merge vertically. And vice versa</remarks>
private CoveredCellInfo GetRange(GridColumn column, int rowIndex, int columnIndex, object rowData)
{
            var range = new CoveredCellInfo(columnIndex, columnIndex, rowIndex, rowIndex);
            object data = reflector.GetFormattedValue(rowData, column.MappingName);

            //here get the Product value for checking other cell value
            string productData = (rowData as ProductSalesDetails).Product;

            GridColumn leftColumn = null;
            GridColumn rightColumn = null;

            // total rows count.
            int recordsCount = this.sfDataGrid.GroupColumnDescriptions.Count != 0 ?
            (this.sfDataGrid.View.TopLevelGroup.DisplayElements.Count + this.sfDataGrid.TableSummaryRows.Count + this.sfDataGrid.UnboundRows.Count + (this.sfDataGrid.AddNewRowPosition == AddNewRowPosition.Top ? +1 : 0)) :
            (this.sfDataGrid.View.Records.Count + this.sfDataGrid.TableSummaryRows.Count + this.sfDataGrid.UnboundRows.Count + (this.sfDataGrid.AddNewRowPosition == AddNewRowPosition.Top ? +1 : 0));

            // Merge Horizontally

            // compare right column
            for (int i = sfDataGrid.Columns.IndexOf(column); i < this.sfDataGrid.Columns.Count - 1; i++)
            {
                var compareData = reflector.GetFormattedValue(rowData, sfDataGrid.Columns[i + 1].MappingName);

                if (compareData == null)
                    break;

                if (!compareData.Equals(data))
                    break;
                rightColumn = sfDataGrid.Columns[i + 1];
            }

            // compare left column.
            for (int i = sfDataGrid.Columns.IndexOf(column); i > 0; i--)
            {
                var compareData = reflector.GetFormattedValue(rowData, sfDataGrid.Columns[i - 1].MappingName);

                if (compareData == null)
                    break;

                if (!compareData.Equals(data))
                    break;
                leftColumn = sfDataGrid.Columns[i - 1];
            }

            if (leftColumn != null || rightColumn != null)
            {

                // set left index
                if (leftColumn != null)
                {
                    var leftColumnIndex = this.sfDataGrid.ResolveToScrollColumnIndex(this.sfDataGrid.Columns.IndexOf(leftColumn));
                    range = new CoveredCellInfo(leftColumnIndex, range.Right, range.Top, range.Bottom);
                }

                // set right index
                if (rightColumn != null)
                {
                    var rightColumnIndex = this.sfDataGrid.ResolveToScrollColumnIndex(this.sfDataGrid.Columns.IndexOf(rightColumn));
                    range = new CoveredCellInfo(range.Left, rightColumnIndex, range.Top, range.Bottom);
                }
                return range;
            }

            // Merge Vertically from the row index.
            int previousRowIndex = -1;
            int nextRowIndex = -1;
            object previousData = null;

            // Get previous row data.
            var startIndex = sfDataGrid.ResolveStartIndexBasedOnPosition();

            for (int i = rowIndex - 1; i >= startIndex; i--)
            {
                var recordIndex = this.sfDataGrid.ResolveToRecordIndex(i);
                if (this.sfDataGrid.View.GroupDescriptions.Count > 0)
                {
                    previousData = this.sfDataGrid.View.TopLevelGroup.DisplayElements[recordIndex];
                }
                else
                {
                    var recordCount = this.sfDataGrid.View.Records.Count;
                    previousData = (recordCount > 0 && recordIndex >= 0 && recordIndex < recordCount)
                               ? sfDataGrid.View.Records[recordIndex]
                               : null;
                }

                if (previousData == null || !(previousData as NodeEntry).IsRecords)
                    break;
                var compareData = reflector.GetFormattedValue((previousData as RecordEntry).Data, column.MappingName);

                //get the previous row data value of Product
                string productPreviousData = ((previousData as RecordEntry).Data as ProductSalesDetails).Product;

                if (compareData == null)
                    break;

                if (!compareData.Equals(data))
                    break;

                //here check the value
                if (!productData.Equals(productPreviousData))
                    break;

                previousRowIndex = i;
            }

            // get next row data.
            object nextData = null;
            for (int i = rowIndex + 1; i < recordsCount + 1; i++)
            {
                var recordIndex = this.sfDataGrid.ResolveToRecordIndex(i);
                if (this.sfDataGrid.View.GroupDescriptions.Count > 0)
                {
                    nextData = this.sfDataGrid.View.TopLevelGroup.DisplayElements[recordIndex];
                }
                else
                {
                    var recordCount = this.sfDataGrid.View.Records.Count;
                    nextData = (recordCount > 0 && recordIndex >= 0 && recordIndex < recordCount)
                               ? sfDataGrid.View.Records[recordIndex]
                               : null;
                }

                if (nextData == null || !(nextData as NodeEntry).IsRecords)
                    break;
                var compareData = reflector.GetFormattedValue((nextData as RecordEntry).Data, column.MappingName);

                //get the next row data value of Product
                string productNextData = ((nextData as RecordEntry).Data as ProductSalesDetails).Product;

                if (compareData == null)
                    break;

                if (!compareData.Equals(data))
                    break;

                //here check the value
                if (!productData.Equals(productNextData))
                    break;

                nextRowIndex = i;
            }

            if (previousRowIndex != -1 || nextRowIndex != -1)
            {

                if (previousRowIndex != -1)
                    range = new CoveredCellInfo(range.Left, range.Right, previousRowIndex, range.Bottom);

                if (nextRowIndex != -1)
                    range = new CoveredCellInfo(range.Left, range.Right, range.Top, nextRowIndex);
                return range;
            }
            return null;
}

The following screenshot shows the merged cells in DataGrid,

Shows the merged cells in SfDataGrid

Take a moment to peruse the WinUI DataGrid - Merge Cells documentation, where you can find about merge Cells with code examples.

Requirements to run the demo

Visual Studio 2019 and above versions

About

This example describes how to merge the cells based on its content and value of a specific column in WinUI DataGrid.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages