@@ -21,34 +21,34 @@ IPropertyAccessProvider reflector = null;
2121/// </summary >
2222private void OnItemsSourceChanged (object sender , GridItemsSourceChangedEventArgs e )
2323{
24- if (sfDataGrid .View != null )
25- reflector = sfDataGrid .View .GetPropertyAccessProvider ();
26- else
27- reflector = null ;
24+ if (sfDataGrid .View != null )
25+ reflector = sfDataGrid .View .GetPropertyAccessProvider ();
26+ else
27+ reflector = null ;
2828}
2929
3030/// <summary >
3131/// QueryCoveredRange event handler
3232/// </summary >
3333private void OnQueryCoveredRange (object sender , GridQueryCoveredRangeEventArgs e )
3434{
35- CoveredCellInfo range = null ;
35+ CoveredCellInfo range = null ;
3636
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 );
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 );
4040
41- if (range == null )
42- return ;
41+ if (range == null )
42+ return ;
4343
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- }
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+ }
5050
51- // If the calculated range is already exist in CoveredCells, you can get the range using SfDataGrid.GetConflictRange (CoveredCellInfo coveredCellInfo) extension method.
51+ // If the calculated range is already exist in CoveredCells, you can get the range using SfDataGrid.GetConflictRange (CoveredCellInfo coveredCellInfo) extension method.
5252 }
5353
5454/// <summary >
@@ -60,162 +60,161 @@ private void OnQueryCoveredRange(object sender, GridQueryCoveredRangeEventArgs e
6060/// <param name =" rowData" ></param >
6161/// <returns > Compares the adjacent cell value and returns the range </returns >
6262/// <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-
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+ }
219218```
220219
221220The following screenshot shows the merged cells in DataGrid,
0 commit comments