Good evening,
I was trying to implement a generic column where depending the type of object being bind to it, different editors would be used.
At this moment i've settled for boolean, text and list and everyting is working well except the display of the checkbox.
The following happens: GridVirtualization
As you can see in the picture above, the top of the grid shows up fine, but on the bottom the checkboxes show up as text, as i use the scroll bar the lines eventually refresh to display the checkboxes(wich is why i assume this is something regarding the UI Virtualization).
I have tried invallidating rows, using dgvCustomer.TableElement.Update(Telerik.WinControls.UI.GridUINotifyAction.Reset) and a couple of alternatives that i have forgotten meantime.
The setup uses 3 custom cells, and the following custom column.
01.
using
System;
02.
using
System.Collections.Generic;
03.
using
Telerik.WinControls.UI;
04.
05.
namespace
Inl.TelerikExtensions40.WinForms
06.
{
07.
public
class
GenericDataColumn : GridViewDataColumn
08.
{
09.
10.
public
GenericDataColumn() :
base
()
11.
{
12.
}
13.
14.
public
GenericDataColumn(
string
fieldName) :
base
(fieldName)
15.
{
16.
}
17.
18.
public
GenericDataColumn(
string
uniqueName,
string
fieldName) :
base
(uniqueName, fieldName)
19.
{
20.
}
21.
22.
public
override
Type GetCellType(GridViewRowInfo row)
23.
{
24.
if
(row
is
GridViewDataRowInfo)
25.
{
26.
if
(row.Tag !=
null
)
27.
{
28.
var types = (Dictionary<
int
, Type>)row.Tag;
29.
if
(types.ContainsKey(
base
.Index))
30.
{
31.
return
types[
base
.Index];
32.
}
33.
}
34.
35.
return
typeof
(CustomTextBoxCell);
36.
}
37.
return
base
.GetCellType(row);
38.
}
39.
40.
public
override
Type GetDefaultEditorType()
41.
{
42.
var cellType = GetCellType(
base
.OwnerTemplate.DataView.CurrentItem);
43.
44.
if
(cellType ==
typeof
(CustomTextBoxCell)) {
45.
return
typeof
(RadTextBoxEditor);
46.
}
47.
if
(cellType ==
typeof
(CustomCheckBoxCell))
48.
{
49.
return
typeof
(CustomCheckBoxEditor);
50.
}
51.
if
(cellType ==
typeof
(CustomComboBoxCell))
52.
{
53.
return
typeof
(RadDropDownListEditor);
54.
}
55.
56.
return
base
.GetDefaultEditorType();
57.
}
58.
59.
public
void
SetType(Enumeration.DataTypesEnum tipo, GridViewRowInfo row)
60.
{
61.
Dictionary<
int
, Type> types =
default
(Dictionary<
int
, Type>);
62.
63.
if
(row.Tag !=
null
)
64.
{
65.
types = (Dictionary<
int
, Type>)row.Tag;
66.
}
67.
else
68.
{
69.
types =
new
Dictionary<
int
, Type>();
70.
}
71.
72.
if
(types.ContainsKey(
base
.Index) ==
false
)
73.
{
74.
switch
(tipo)
75.
{
76.
case
Enumeration.DataTypesEnum.Texto:
77.
types.Add(
base
.Index,
typeof
(CustomTextBoxCell));
78.
break
;
79.
case
Enumeration.DataTypesEnum.Booleano:
80.
types.Add(
base
.Index,
typeof
(CustomCheckBoxCell));
81.
break
;
82.
case
Enumeration.DataTypesEnum.Lista:
83.
types.Add(
base
.Index,
typeof
(CustomComboBoxCell));
84.
break
;
85.
}
86.
}
87.
88.
row.Tag = types;
89.
//row.InvalidateRow();
90.
}
91.
}
92.
}
I'll be willing to supply any other code necessary.
Thank you in advance.
9 Answers, 1 is accepted
Thank you for writing.
Thanks to the UI virtualization mechanism in RadGridView only the currently visible cells are created and they are further reused when needed. A cell element is reused in other rows or columns if it is compatible with them. You can create a custom column and define that the custom cell is compatible with that column only. This will prevent the cell from being unintentionally reused by other columns. For this purpose, it is necessary to override the IsCompatible method of the custom cell and return true only for columns and rows that are eligible. You can find a sample approach in the following help article: http://docs.telerik.com/devtools/winforms/gridview/cells/creating-custom-cells
I hope this information helps. Should you have further questions I would be glad to help.
Regards,
Dess
Progress Telerik
Hello Dess,
Thank you for the answer.
I am aware of that behaviour wich is why i assumed it could be related to the UI Virtualization. This is just a wild guess but the best i have so far, since the form opens at a specific size before maximizing itself those checkboxes show up correctly, and after tthat the window and as such the grid expand in size but the grid cells that are visible to the user somehow are not refreshed(untill i edit the value of a cell, or scroll the vertical bar). It would be really important for me to solve this visual effect, i'll add the code for custumn cells, editor and form. Thanks again.
01.
using
System;
02.
using
Telerik.WinControls.UI;
03.
04.
namespace
Inl.TelerikExtensions40.WinForms
05.
{
06.
public
class
CustomComboBoxCell : GridDataCellElement
07.
{
08.
09.
public
CustomComboBoxCell(GridViewColumn column, GridRowElement row) :
base
(column, row)
10.
{
11.
}
12.
13.
protected
override
Type ThemeEffectiveType
14.
{
15.
get
{
return
typeof
(GridDataCellElement); }
16.
}
17.
18.
public
override
bool
IsCompatible(GridViewColumn data,
object
context)
19.
{
20.
return
data
is
GenericDataColumn && context
is
GridDataRowElement;
21.
}
22.
23.
}
24.
}
01.
using
System;
02.
using
Telerik.WinControls.UI;
03.
04.
namespace
Inl.TelerikExtensions40.WinForms
05.
{
06.
public
class
CustomTextBoxCell : GridDataCellElement
07.
{
08.
public
CustomTextBoxCell(GridViewColumn column, GridRowElement row) :
base
(column, row)
09.
{
10.
}
11.
12.
protected
override
Type ThemeEffectiveType
13.
{
14.
get
{
return
typeof
(GridDataCellElement); }
15.
}
16.
17.
public
override
bool
IsCompatible(GridViewColumn data,
object
context)
18.
{
19.
return
data
is
GenericDataColumn && context
is
GridDataRowElement;
20.
}
21.
22.
}
23.
24.
}
01.
using
System;
02.
using
System.Drawing;
03.
using
Telerik.WinControls.UI;
04.
05.
namespace
Inl.TelerikExtensions40.WinForms
06.
{
07.
public
class
CustomCheckBoxCell : GridDataCellElement
08.
{
09.
10.
public
RadCheckBoxElement radCheckBoxElement;
11.
12.
public
CustomCheckBoxCell(GridViewColumn column, GridRowElement row) :
base
(column, row)
13.
{
14.
}
15.
16.
protected
override
void
CreateChildElements()
17.
{
18.
base
.CreateChildElements();
19.
radCheckBoxElement =
new
RadCheckBoxElement();
20.
radCheckBoxElement.ReadOnly =
true
;
21.
radCheckBoxElement.IsThreeState =
true
;
22.
Children.Add(
this
.radCheckBoxElement);
23.
}
24.
25.
protected
override
SizeF ArrangeOverride(SizeF finalSize)
26.
{
27.
SizeF size =
base
.ArrangeOverride(finalSize);
28.
this
.radCheckBoxElement.Arrange(
new
RectangleF((finalSize.Width -
this
.radCheckBoxElement.DesiredSize.Width) / 2f, (finalSize.Height -
this
.radCheckBoxElement.DesiredSize.Height) / 2f,
this
.radCheckBoxElement.DesiredSize.Width,
this
.radCheckBoxElement.DesiredSize.Height));
29.
return
size;
30.
}
31.
32.
protected
override
void
SetContentCore(
object
value)
33.
{
34.
if
(
this
.Value !=
null
&& !
object
.ReferenceEquals(
this
.Value, DBNull.Value))
35.
{
36.
if
(value.ToString() ==
"Indeterminate"
)
37.
{
38.
radCheckBoxElement.ToggleState = Telerik.WinControls.Enumerations.ToggleState.Indeterminate;
39.
}
40.
else
if
(value.ToString() ==
"On"
)
41.
{
42.
radCheckBoxElement.ToggleState = Telerik.WinControls.Enumerations.ToggleState.On;
43.
}
44.
else
45.
{
46.
radCheckBoxElement.ToggleState = Telerik.WinControls.Enumerations.ToggleState.Off;
47.
}
48.
}
49.
else
50.
{
51.
radCheckBoxElement.ToggleState = Telerik.WinControls.Enumerations.ToggleState.Indeterminate;
52.
}
53.
}
54.
55.
protected
override
Type ThemeEffectiveType
56.
{
57.
get
{
return
typeof
(GridDataCellElement); }
58.
}
59.
60.
public
override
bool
IsCompatible(GridViewColumn data,
object
context)
61.
{
62.
return
data
is
GenericDataColumn && context
is
GridDataRowElement;
63.
}
64.
}
65.
}
01.
using
Inl.TelerikExtensions40.WinForms;
02.
using
System;
03.
using
Telerik.WinControls.UI;
04.
05.
namespace
Inl.TelerikExtensions40.Tests
06.
{
07.
public
partial
class
FrmGridView : Telerik.WinControls.UI.RadForm
08.
{
09.
public
FrmGridView()
10.
{
11.
InitializeComponent();
12.
}
13.
14.
private
void
btnExport_Click(
object
sender, EventArgs e)
15.
{
16.
Inl.TelerikExtensions40.WinForms.RadGridView.Export(dgvCustomer);
17.
}
18.
19.
private
void
dgvCustomer_CellFormatting(
object
sender, CellFormattingEventArgs e)
20.
{
21.
var costumer = (DataSource.Customer)e.Row.DataBoundItem;
22.
if
(e.Column.GetType().Name == nameof(GenericDataColumn))
23.
{
24.
((GenericDataColumn)e.Column).SetType(costumer.TipoDeValor, e.Row);
25.
}
26.
}
27.
28.
private
void
dgvCustomer_DataBindingComplete(
object
sender, GridViewBindingCompleteEventArgs e)
29.
{
30.
dgvCustomer.TableElement.Update(Telerik.WinControls.UI.GridUINotifyAction.Reset);
31.
}
32.
33.
private
void
FrmGridView_Load(
object
sender, EventArgs e)
34.
{
35.
customerBindingSource.DataSource = DataSource.Customer.GetList(1000);
36.
customerBindingSource.ResetBindings(
false
);
37.
WinForms.RadGridView.EnableBetterSearchRow(dgvCustomer);
38.
}
39.
}
40.
}
01.
using
System.Drawing;
02.
using
Telerik.WinControls;
03.
using
Telerik.WinControls.UI;
04.
05.
namespace
Inl.TelerikExtensions40.WinForms
06.
{
07.
class
CustomCheckBoxEditor : BaseGridEditor
08.
{
09.
public
override
object
Value
10.
{
11.
get
12.
{
13.
var element = (RadCheckBoxElement)
this
.EditorElement;
14.
return
element.ToggleState.ToString();
15.
}
16.
17.
set
18.
{
19.
var element = (RadCheckBoxElement)
this
.EditorElement;
20.
if
(value.ToString() ==
"Indeterminate"
)
21.
{
22.
element.ToggleState = Telerik.WinControls.Enumerations.ToggleState.Indeterminate;
23.
}
24.
else
if
(value.ToString() ==
"On"
)
25.
{
26.
element.ToggleState = Telerik.WinControls.Enumerations.ToggleState.On;
27.
}
28.
else
29.
{
30.
element.ToggleState = Telerik.WinControls.Enumerations.ToggleState.Off;
31.
}
32.
}
33.
}
34.
protected
override
RadElement CreateEditorElement()
35.
{
36.
return
new
RadCheckBoxElement() { IsThreeState =
true
, Alignment = ContentAlignment.MiddleCenter, CheckAlignment = ContentAlignment.MiddleCenter };
37.
}
38.
}
39.
}
Thank you for writing back.
The provided sample code snippet is greatly appreciated. In the IsCompatible method, each of the cell elements returns true if the column is GenericDataColumn. This means that all of the columns are compatible with each other. I would recommend you to add a condition for the column's name as well. Thus, the cell element will be compatible only with one specific column. In addition, create one custom GridDataCellElement that will be used for default cell. In its IsCompatible method, this default cell should be compatible with all columns except the custom ones.
I hope this information helps. If you have any additional questions, please let me know.
Regards,
Dess
Progress Telerik
Hi again Dess,
Thank you for everything so far.
I was left a bit confused so i'm just making sure but:
"This means that all of the columns are compatible with each other. I would recommend you to add a condition for the column's name as well."
Did you mean all of the cells are compatible with each other?
"In its IsCompatible method, this default cell should be compatible with all columns except the custom ones."
I'm completly lost on this one.
If it's not asking too much, some snippets would be extremely appreciated.
Thank you again
Thank you for writing back.
Firstly, I would like to note that RadGridView offers GridViewCheckBoxColumn which displays and allows editing of boolean data. The values are shown as checkboxes and allow the user to set or clear the check boxes to toggle the underlying boolean data values. Additional information is available here: http://docs.telerik.com/devtools/winforms/gridview/columns/column-types/gridviewcheckboxcolumn
An alternative solution would be to skip creating custom cells, but handle the EditorRequired event and specify what editor to be used. The following help article is quite useful on this topic: http://docs.telerik.com/devtools/winforms/gridview/editors/how-to/change-the-active-editor-depending-on-the-cell-value-type.
I have prepared a sample project for your reference using your code snippets. When you perform scrolling, everything works as expected.
I hope this information helps. If you have any additional questions, please let me know.
Regards,
Dess
Progress Telerik
Yes, but the main goal with creating this GenericColumn is to use different object types, on the same column.
I noticed something on the sample project you sent me that used the create cell event.
Using the type being bound to the column i create the specific celltype i wish and it seems to be working properly, i'm also adding your tip on the generic cell.
Will just perform a couple more tests during the day, and if nothing rises up i'll come back to mark the question as answered.
Again, thank you for everything Dess, much appreciated.
Thank you for writing back.
I am glad that the provided sample project was useful. Feel free to test as long as you need.
If you have any additional questions, please let me know.
Regards,
Dess
Progress Telerik
Hi Dess,
Thank you so much for the help. Every test i've run so far as went well.
I'm marking this question as answered, but on a side note and as a last question: Is there any way i can override the createcell event: on the cell level or column level? wanted to keep as much code as possible 'under the hood' but i know its a longshot.
Again, thanks for everything.
Thank you for writing back.
The CreateCell event is at RadGridView level. You can't switch it to column or cell level. This event is purposed to be fired when the grid creates the visual cell elements and it is necessary to provide the cell type that needs to be used considering the row and column.
I hope this information helps. If you have any additional questions, please let me know.
Regards,
Dess
Progress Telerik