Skip to content

Commit 76f27b8

Browse files
Merge pull request #1 from vijayarasan/main
How to merge the cells based on its content and value of a specific column in WinUI DataGrid (SfDataGrid)?
2 parents 74de749 + 136f658 commit 76f27b8

26 files changed

+1068
-0
lines changed

MergecellbasedonContent.gif

10.9 MB
Loading

MergedCell.png

17.9 KB
Loading

README.md

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,228 @@
11
# How to merge the cells based on its content and value of a specific column in WinUI DataGrid?
2+
3+
## About the sample
4+
25
This example describes how to merge the cells based on its content and value of a specific column in WinUI DataGrid.
6+
7+
[WinUI DataGrid](https://www.syncfusion.com/winui-controls/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](https://help.syncfusion.com/cr/winui/Syncfusion.UI.Xaml.DataGrid.SfDataGrid.html#Syncfusion_UI_Xaml_DataGrid_SfDataGrid_QueryCoveredRange) event in DataGrid.
8+
9+
``` C#
10+
11+
this.sfDataGrid.ItemsSourceChanged += OnItemsSourceChanged;
12+
this.sfDataGrid.QueryCoveredRange += OnQueryCoveredRange;
13+
14+
/// <summary>
15+
/// Reflector for SfDataGrid’s data.
16+
/// </summary>
17+
IPropertyAccessProvider reflector = null;
18+
19+
/// <summary>
20+
/// ItemsSourceChanged event handler.
21+
/// </summary>
22+
private void OnItemsSourceChanged(object sender, GridItemsSourceChangedEventArgs e)
23+
{
24+
if (sfDataGrid.View != null)
25+
reflector = sfDataGrid.View.GetPropertyAccessProvider();
26+
else
27+
reflector = null;
28+
}
29+
30+
/// <summary>
31+
/// QueryCoveredRange event handler
32+
/// </summary>
33+
private void OnQueryCoveredRange(object sender, GridQueryCoveredRangeEventArgs e)
34+
{
35+
CoveredCellInfo range = null;
36+
37+
////here apply merge the cell based on Columns
38+
if (e.GridColumn.MappingName == "Product" || e.GridColumn.MappingName == "Country" )
39+
range = GetRange(e.GridColumn, e.RowColumnIndex.RowIndex, e.RowColumnIndex.ColumnIndex, e.Record);
40+
41+
if (range == null)
42+
return;
43+
44+
// You can know that the range is already exist in Covered Cells by IsInRange method.
45+
if (!sfDataGrid.CoveredCells.IsInRange(range))
46+
{
47+
e.Range = range;
48+
e.Handled = true;
49+
}
50+
51+
//If the calculated range is already exist in CoveredCells, you can get the range using SfDataGrid.GetConflictRange (CoveredCellInfo coveredCellInfo) extension method.
52+
}
53+
54+
/// <summary>
55+
/// Method to get the covered range based on cell value.
56+
/// </summary>
57+
/// <param name="column"></param>
58+
/// <param name="rowIndex"></param>
59+
/// <param name="columnIndex"></param>
60+
/// <param name="rowData"></param>
61+
/// <returns> Compares the adjacent cell value and returns the range </returns>
62+
/// <remark> If the method find that the adjacent values are equal by horizontal then it will merge vertically. And vice versa</remarks>
63+
private CoveredCellInfo GetRange(GridColumn column, int rowIndex, int columnIndex, object rowData)
64+
{
65+
var range = new CoveredCellInfo(columnIndex, columnIndex, rowIndex, rowIndex);
66+
object data = reflector.GetFormattedValue(rowData, column.MappingName);
67+
68+
//here get the Product value for checking other cell value
69+
string productData = (rowData as ProductSalesDetails).Product;
70+
71+
GridColumn leftColumn = null;
72+
GridColumn rightColumn = null;
73+
74+
// total rows count.
75+
int recordsCount = this.sfDataGrid.GroupColumnDescriptions.Count != 0 ?
76+
(this.sfDataGrid.View.TopLevelGroup.DisplayElements.Count + this.sfDataGrid.TableSummaryRows.Count + this.sfDataGrid.UnboundRows.Count + (this.sfDataGrid.AddNewRowPosition == AddNewRowPosition.Top ? +1 : 0)) :
77+
(this.sfDataGrid.View.Records.Count + this.sfDataGrid.TableSummaryRows.Count + this.sfDataGrid.UnboundRows.Count + (this.sfDataGrid.AddNewRowPosition == AddNewRowPosition.Top ? +1 : 0));
78+
79+
// Merge Horizontally
80+
81+
// compare right column
82+
for (int i = sfDataGrid.Columns.IndexOf(column); i < this.sfDataGrid.Columns.Count - 1; i++)
83+
{
84+
var compareData = reflector.GetFormattedValue(rowData, sfDataGrid.Columns[i + 1].MappingName);
85+
86+
if (compareData == null)
87+
break;
88+
89+
if (!compareData.Equals(data))
90+
break;
91+
rightColumn = sfDataGrid.Columns[i + 1];
92+
}
93+
94+
// compare left column.
95+
for (int i = sfDataGrid.Columns.IndexOf(column); i > 0; i--)
96+
{
97+
var compareData = reflector.GetFormattedValue(rowData, sfDataGrid.Columns[i - 1].MappingName);
98+
99+
if (compareData == null)
100+
break;
101+
102+
if (!compareData.Equals(data))
103+
break;
104+
leftColumn = sfDataGrid.Columns[i - 1];
105+
}
106+
107+
if (leftColumn != null || rightColumn != null)
108+
{
109+
110+
// set left index
111+
if (leftColumn != null)
112+
{
113+
var leftColumnIndex = this.sfDataGrid.ResolveToScrollColumnIndex(this.sfDataGrid.Columns.IndexOf(leftColumn));
114+
range = new CoveredCellInfo(leftColumnIndex, range.Right, range.Top, range.Bottom);
115+
}
116+
117+
// set right index
118+
if (rightColumn != null)
119+
{
120+
var rightColumnIndex = this.sfDataGrid.ResolveToScrollColumnIndex(this.sfDataGrid.Columns.IndexOf(rightColumn));
121+
range = new CoveredCellInfo(range.Left, rightColumnIndex, range.Top, range.Bottom);
122+
}
123+
return range;
124+
}
125+
126+
// Merge Vertically from the row index.
127+
int previousRowIndex = -1;
128+
int nextRowIndex = -1;
129+
object previousData = null;
130+
131+
// Get previous row data.
132+
var startIndex = sfDataGrid.ResolveStartIndexBasedOnPosition();
133+
134+
for (int i = rowIndex - 1; i >= startIndex; i--)
135+
{
136+
var recordIndex = this.sfDataGrid.ResolveToRecordIndex(i);
137+
if (this.sfDataGrid.View.GroupDescriptions.Count > 0)
138+
{
139+
previousData = this.sfDataGrid.View.TopLevelGroup.DisplayElements[recordIndex];
140+
}
141+
else
142+
{
143+
var recordCount = this.sfDataGrid.View.Records.Count;
144+
previousData = (recordCount > 0 && recordIndex >= 0 && recordIndex < recordCount)
145+
? sfDataGrid.View.Records[recordIndex]
146+
: null;
147+
}
148+
149+
if (previousData == null || !(previousData as NodeEntry).IsRecords)
150+
break;
151+
var compareData = reflector.GetFormattedValue((previousData as RecordEntry).Data, column.MappingName);
152+
153+
//get the previous row data value of Product
154+
string productPreviousData = ((previousData as RecordEntry).Data as ProductSalesDetails).Product;
155+
156+
if (compareData == null)
157+
break;
158+
159+
if (!compareData.Equals(data))
160+
break;
161+
162+
//here check the value
163+
if (!productData.Equals(productPreviousData))
164+
break;
165+
166+
previousRowIndex = i;
167+
}
168+
169+
// get next row data.
170+
object nextData = null;
171+
for (int i = rowIndex + 1; i < recordsCount + 1; i++)
172+
{
173+
var recordIndex = this.sfDataGrid.ResolveToRecordIndex(i);
174+
if (this.sfDataGrid.View.GroupDescriptions.Count > 0)
175+
{
176+
nextData = this.sfDataGrid.View.TopLevelGroup.DisplayElements[recordIndex];
177+
}
178+
else
179+
{
180+
var recordCount = this.sfDataGrid.View.Records.Count;
181+
nextData = (recordCount > 0 && recordIndex >= 0 && recordIndex < recordCount)
182+
? sfDataGrid.View.Records[recordIndex]
183+
: null;
184+
}
185+
186+
if (nextData == null || !(nextData as NodeEntry).IsRecords)
187+
break;
188+
var compareData = reflector.GetFormattedValue((nextData as RecordEntry).Data, column.MappingName);
189+
190+
//get the next row data value of Product
191+
string productNextData = ((nextData as RecordEntry).Data as ProductSalesDetails).Product;
192+
193+
if (compareData == null)
194+
break;
195+
196+
if (!compareData.Equals(data))
197+
break;
198+
199+
//here check the value
200+
if (!productData.Equals(productNextData))
201+
break;
202+
203+
nextRowIndex = i;
204+
}
205+
206+
if (previousRowIndex != -1 || nextRowIndex != -1)
207+
{
208+
209+
if (previousRowIndex != -1)
210+
range = new CoveredCellInfo(range.Left, range.Right, previousRowIndex, range.Bottom);
211+
212+
if (nextRowIndex != -1)
213+
range = new CoveredCellInfo(range.Left, range.Right, range.Top, nextRowIndex);
214+
return range;
215+
}
216+
return null;
217+
}
218+
219+
```
220+
221+
The following screenshot shows the merged cells in DataGrid,
222+
223+
![Shows the merged cells in SfDataGrid](MergedCell.png)
224+
225+
Take a moment to peruse the [WinUI DataGrid - Merge Cells](https://help.syncfusion.com/winui/datagrid/merge-cells) documentation, where you can find about merge Cells with code examples.
226+
227+
## Requirements to run the demo
228+
Visual Studio 2019 and above versions
432 Bytes
Loading
5.25 KB
Loading
1.71 KB
Loading
637 Bytes
Loading
283 Bytes
Loading
456 Bytes
Loading
2.05 KB
Loading

0 commit comments

Comments
 (0)