Hi, I have one problem with Telerik Grid View (version 2014.2.617.40).
I set list with several items as DataSource for GridView and user can add new items by clicking on "Click here to add a new row". But if all items were removed from list this row disappear. Only text "No data to display" is showed.
My collection defined as
After initialization of list user have empty list and cannot add first row. How I can change this behavior?
Thanks.
I set list with several items as DataSource for GridView and user can add new items by clicking on "Click here to add a new row". But if all items were removed from list this row disappear. Only text "No data to display" is showed.
My collection defined as
ItemsCollection<T> : IBindingList, IList<T> where T : Item
{}
After initialization of list user have empty list and cannot add first row. How I can change this behavior?
Thanks.
9 Answers, 1 is accepted
0
Hi Thomas,
Thank you for writing.
The "No data to display" text should be shown only when the grid does not have its DataSource property assigned or if its Columns collection is empty. I have tested the described case and on my end the new row still remains in the grid and I can still add rows to it. Please refer to the attached project and video.
If you still experience issues, please get back to me with information how to replicate it and I will look into it.
Regards,
Stefan
Telerik
Thank you for writing.
The "No data to display" text should be shown only when the grid does not have its DataSource property assigned or if its Columns collection is empty. I have tested the described case and on my end the new row still remains in the grid and I can still add rows to it. Please refer to the attached project and video.
If you still experience issues, please get back to me with information how to replicate it and I will look into it.
Regards,
Stefan
Telerik
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
0
Thomas
Top achievements
Rank 1
answered on 09 Sep 2014, 07:45 AM
Reason of problem was found in implementation of ICustomTypeDescriptor interface. All works fine, when I remove this implementation of ICustomTypeDescriptor. You can find example of class bellow.
Also items which were added programmatically to empty collection are invisible. I cannot remove ICustomTypeDescriptor interface in my case. How I can fix this?
001.
public
class
CustomItem : ICustomTypeDescriptor
002.
{
003.
public
CustomItem(
string
name )
004.
{
005.
Name = name;
006.
}
007.
008.
public
string
Name
009.
{
010.
get
;
011.
set
;
012.
}
013.
014.
#region Implementation of ICustomTypeDescriptor
015.
/// <summary>
016.
/// Returns a collection of custom attributes for this instance of a component.
017.
/// </summary>
018.
/// <returns>
019.
/// An <see cref="T:System.ComponentModel.AttributeCollection"/> containing the attributes for this object.
020.
/// </returns>
021.
public
AttributeCollection GetAttributes()
022.
{
023.
return
TypeDescriptor.GetAttributes(
this
);
024.
}
025.
026.
/// <summary>
027.
/// Returns the class name of this instance of a component.
028.
/// </summary>
029.
/// <returns>
030.
/// The class name of the object, or null if the class does not have a name.
031.
/// </returns>
032.
public
string
GetClassName()
033.
{
034.
return
TypeDescriptor.GetClassName(
this
);
035.
}
036.
037.
/// <summary>
038.
/// Returns the name of this instance of a component.
039.
/// </summary>
040.
/// <returns>
041.
/// The name of the object, or null if the object does not have a name.
042.
/// </returns>
043.
public
string
GetComponentName()
044.
{
045.
return
TypeDescriptor.GetComponentName(
this
);
046.
}
047.
048.
/// <summary>
049.
/// Returns a type converter for this instance of a component.
050.
/// </summary>
051.
/// <returns>
052.
/// A <see cref="T:System.ComponentModel.TypeConverter"/> that is the converter for this object, or null if there is no <see cref="T:System.ComponentModel.TypeConverter"/> for this object.
053.
/// </returns>
054.
public
TypeConverter GetConverter()
055.
{
056.
return
TypeDescriptor.GetConverter(
this
);
057.
}
058.
059.
/// <summary>
060.
/// Returns the default event for this instance of a component.
061.
/// </summary>
062.
/// <returns>
063.
/// An <see cref="T:System.ComponentModel.EventDescriptor"/> that represents the default event for this object, or null if this object does not have events.
064.
/// </returns>
065.
public
EventDescriptor GetDefaultEvent()
066.
{
067.
return
TypeDescriptor.GetDefaultEvent(
this
);
068.
}
069.
070.
/// <summary>
071.
/// Returns the default property for this instance of a component.
072.
/// </summary>
073.
/// <returns>
074.
/// A <see cref="T:System.ComponentModel.PropertyDescriptor"/> that represents the default property for this object, or null if this object does not have properties.
075.
/// </returns>
076.
public
PropertyDescriptor GetDefaultProperty()
077.
{
078.
return
TypeDescriptor.GetDefaultProperty(
this
);
079.
}
080.
081.
/// <summary>
082.
/// Returns an editor of the specified type for this instance of a component.
083.
/// </summary>
084.
/// <returns>
085.
/// An <see cref="T:System.Object"/> of the specified type that is the editor for this object, or null if the editor cannot be found.
086.
/// </returns>
087.
/// <param name="editorBaseType">A <see cref="T:System.Type"/> that represents the editor for this object. </param>
088.
public
object
GetEditor( Type editorBaseType )
089.
{
090.
return
TypeDescriptor.GetEditor(
this
, editorBaseType );
091.
}
092.
093.
/// <summary>
094.
/// Returns the events for this instance of a component.
095.
/// </summary>
096.
/// <returns>
097.
/// An <see cref="T:System.ComponentModel.EventDescriptorCollection"/> that represents the events for this component instance.
098.
/// </returns>
099.
public
EventDescriptorCollection GetEvents()
100.
{
101.
return
TypeDescriptor.GetEvents(
this
);
102.
}
103.
104.
/// <summary>
105.
/// Returns the events for this instance of a component using the specified attribute array as a filter.
106.
/// </summary>
107.
/// <returns>
108.
/// An <see cref="T:System.ComponentModel.EventDescriptorCollection"/> that represents the filtered events for this component instance.
109.
/// </returns>
110.
/// <param name="attributes">An array of type <see cref="T:System.Attribute"/> that is used as a filter. </param>
111.
public
EventDescriptorCollection GetEvents( Attribute[] attributes )
112.
{
113.
return
TypeDescriptor.GetEvents(
this
, attributes );
114.
}
115.
116.
/// <summary>
117.
/// Returns the properties for this instance of a component.
118.
/// </summary>
119.
/// <returns>
120.
/// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> that represents the properties for this component instance.
121.
/// </returns>
122.
public
PropertyDescriptorCollection GetProperties()
123.
{
124.
return
TypeDescriptor.GetProperties(
this
);
125.
}
126.
127.
/// <summary>
128.
/// Returns the properties for this instance of a component using the attribute array as a filter.
129.
/// </summary>
130.
/// <returns>
131.
/// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> that represents the filtered properties for this component instance.
132.
/// </returns>
133.
/// <param name="attributes">An array of type <see cref="T:System.Attribute"/> that is used as a filter. </param>
134.
public
PropertyDescriptorCollection GetProperties( Attribute[] attributes )
135.
{
136.
return
TypeDescriptor.GetProperties(
this
, attributes );
137.
}
138.
139.
/// <summary>
140.
/// Returns an object that contains the property described by the specified property descriptor.
141.
/// </summary>
142.
/// <returns>
143.
/// An <see cref="T:System.Object"/> that represents the owner of the specified property.
144.
/// </returns>
145.
/// <param name="pd">A <see cref="T:System.ComponentModel.PropertyDescriptor"/> that represents the property whose owner is to be found. </param>
146.
public
object
GetPropertyOwner( PropertyDescriptor pd )
147.
{
148.
return
null
;
149.
}
150.
#endregion
151.
}
1.
radGridView1.DataSource =
new
BindingList<CustomItem>();
Also items which were added programmatically to empty collection are invisible. I cannot remove ICustomTypeDescriptor interface in my case. How I can fix this?
0
Thomas
Top achievements
Rank 1
answered on 09 Sep 2014, 07:46 AM
Reason of problem was found in implementation of ICustomTypeDescriptor interface. All works fine, when I remove this implementation of ICustomTypeDescriptor. You can find example of class bellow.
Usage
Also items which were added programmatically to empty collection are invisible. I cannot remove ICustomTypeDescriptor interface in my case. How I can fix this?
public
class
CustomItem : ICustomTypeDescriptor
{
public
CustomItem(
string
name )
{
Name = name;
}
public
string
Name
{
get
;
set
;
}
#region Implementation of ICustomTypeDescriptor
/// <summary>
/// Returns a collection of custom attributes for this instance of a component.
/// </summary>
/// <returns>
/// An <see cref="T:System.ComponentModel.AttributeCollection"/> containing the attributes for this object.
/// </returns>
public
AttributeCollection GetAttributes()
{
return
TypeDescriptor.GetAttributes(
this
);
}
/// <summary>
/// Returns the class name of this instance of a component.
/// </summary>
/// <returns>
/// The class name of the object, or null if the class does not have a name.
/// </returns>
public
string
GetClassName()
{
return
TypeDescriptor.GetClassName(
this
);
}
/// <summary>
/// Returns the name of this instance of a component.
/// </summary>
/// <returns>
/// The name of the object, or null if the object does not have a name.
/// </returns>
public
string
GetComponentName()
{
return
TypeDescriptor.GetComponentName(
this
);
}
/// <summary>
/// Returns a type converter for this instance of a component.
/// </summary>
/// <returns>
/// A <see cref="T:System.ComponentModel.TypeConverter"/> that is the converter for this object, or null if there is no <see cref="T:System.ComponentModel.TypeConverter"/> for this object.
/// </returns>
public
TypeConverter GetConverter()
{
return
TypeDescriptor.GetConverter(
this
);
}
/// <summary>
/// Returns the default event for this instance of a component.
/// </summary>
/// <returns>
/// An <see cref="T:System.ComponentModel.EventDescriptor"/> that represents the default event for this object, or null if this object does not have events.
/// </returns>
public
EventDescriptor GetDefaultEvent()
{
return
TypeDescriptor.GetDefaultEvent(
this
);
}
/// <summary>
/// Returns the default property for this instance of a component.
/// </summary>
/// <returns>
/// A <see cref="T:System.ComponentModel.PropertyDescriptor"/> that represents the default property for this object, or null if this object does not have properties.
/// </returns>
public
PropertyDescriptor GetDefaultProperty()
{
return
TypeDescriptor.GetDefaultProperty(
this
);
}
/// <summary>
/// Returns an editor of the specified type for this instance of a component.
/// </summary>
/// <returns>
/// An <see cref="T:System.Object"/> of the specified type that is the editor for this object, or null if the editor cannot be found.
/// </returns>
/// <param name="editorBaseType">A <see cref="T:System.Type"/> that represents the editor for this object. </param>
public
object
GetEditor( Type editorBaseType )
{
return
TypeDescriptor.GetEditor(
this
, editorBaseType );
}
/// <summary>
/// Returns the events for this instance of a component.
/// </summary>
/// <returns>
/// An <see cref="T:System.ComponentModel.EventDescriptorCollection"/> that represents the events for this component instance.
/// </returns>
public
EventDescriptorCollection GetEvents()
{
return
TypeDescriptor.GetEvents(
this
);
}
/// <summary>
/// Returns the events for this instance of a component using the specified attribute array as a filter.
/// </summary>
/// <returns>
/// An <see cref="T:System.ComponentModel.EventDescriptorCollection"/> that represents the filtered events for this component instance.
/// </returns>
/// <param name="attributes">An array of type <see cref="T:System.Attribute"/> that is used as a filter. </param>
public
EventDescriptorCollection GetEvents( Attribute[] attributes )
{
return
TypeDescriptor.GetEvents(
this
, attributes );
}
/// <summary>
/// Returns the properties for this instance of a component.
/// </summary>
/// <returns>
/// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> that represents the properties for this component instance.
/// </returns>
public
PropertyDescriptorCollection GetProperties()
{
return
TypeDescriptor.GetProperties(
this
);
}
/// <summary>
/// Returns the properties for this instance of a component using the attribute array as a filter.
/// </summary>
/// <returns>
/// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> that represents the filtered properties for this component instance.
/// </returns>
/// <param name="attributes">An array of type <see cref="T:System.Attribute"/> that is used as a filter. </param>
public
PropertyDescriptorCollection GetProperties( Attribute[] attributes )
{
return
TypeDescriptor.GetProperties(
this
, attributes );
}
/// <summary>
/// Returns an object that contains the property described by the specified property descriptor.
/// </summary>
/// <returns>
/// An <see cref="T:System.Object"/> that represents the owner of the specified property.
/// </returns>
/// <param name="pd">A <see cref="T:System.ComponentModel.PropertyDescriptor"/> that represents the property whose owner is to be found. </param>
public
object
GetPropertyOwner( PropertyDescriptor pd )
{
return
null
;
}
#endregion
}
radGridView1.DataSource =
new
BindingList<CustomItem>();
0
Hello Thomas,
Thank you for writing back.
The problem was coming from the implementation of the ICustomTypeDescriptor interface. Here's how the GetProperties, GetProperties(Attribute[] attributes) and GetPropertyOwner should be implemented:
I hope this information will help.
Regards,
George
Telerik
Thank you for writing back.
The problem was coming from the implementation of the ICustomTypeDescriptor interface. Here's how the GetProperties, GetProperties(Attribute[] attributes) and GetPropertyOwner should be implemented:
public
PropertyDescriptorCollection GetProperties()
{
return
TypeDescriptor.GetProperties(
this
,
true
);
}
public
PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
List<PropertyDescriptor> descriptors =
new
List<PropertyDescriptor>();
foreach
(PropertyDescriptor descriptor
in
this
.GetProperties())
{
bool
include =
false
;
foreach
(Attribute searchAttribute
in
attributes)
{
if
(descriptor.Attributes.Contains(searchAttribute))
{
include =
true
;
break
;
}
}
if
(include)
{
descriptors.Add(descriptor);
}
}
return
new
PropertyDescriptorCollection(descriptors.ToArray());
}
public
object
GetPropertyOwner(PropertyDescriptor pd)
{
return
this
;
}
I hope this information will help.
Regards,
George
Telerik
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
0
Thomas
Top achievements
Rank 1
answered on 15 Sep 2014, 07:24 AM
Hello George,
Thanks you for answer. I implemented your suggestions but it does not work. RadGridView still shows message "No data to display". Can you give me example which will show implementation of ICustomTypeDescriptor for working with RadGridView or link to example.
Thanks.
Thanks you for answer. I implemented your suggestions but it does not work. RadGridView still shows message "No data to display". Can you give me example which will show implementation of ICustomTypeDescriptor for working with RadGridView or link to example.
Thanks.
0
Hi Thomas,
Thank you for your reply.
I am attaching a sample project with a RadGridView bound to such items. You can find it below.
Let me know, should you have other questions.
Regards,
George
Telerik
Thank you for your reply.
I am attaching a sample project with a RadGridView bound to such items. You can find it below.
Let me know, should you have other questions.
Regards,
George
Telerik
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
0
Thomas
Top achievements
Rank 1
answered on 17 Sep 2014, 03:29 PM
Hello George,
Thanks you for answer. I downloaded your example and ran it. It works fine but you use not empty BindingList. I wrote that list is empty after initialization and user cannot add first row. When I commented lines 20-24 (Form1.cs) in your example and attached empty BIndingList to DataGridView, row with text "Click here to add a new row" is absent. So user cannot add first row when run program first time. Also I tried to add button for creating first row when list is empty. But It does not work too. New items do not appear in grid. The reason of all issues is ICustomTypeDescriptor. When I removed it from example all forks fine, but I cannot remove it from my project.
I am using version 2014.2.715.40.
How I can fix this?
Thanks you for answer. I downloaded your example and ran it. It works fine but you use not empty BindingList. I wrote that list is empty after initialization and user cannot add first row. When I commented lines 20-24 (Form1.cs) in your example and attached empty BIndingList to DataGridView, row with text "Click here to add a new row" is absent. So user cannot add first row when run program first time. Also I tried to add button for creating first row when list is empty. But It does not work too. New items do not appear in grid. The reason of all issues is ICustomTypeDescriptor. When I removed it from example all forks fine, but I cannot remove it from my project.
I am using version 2014.2.715.40.
How I can fix this?
0
Accepted
Hello Thomas,
Thank you for writing back.
When you bind the grid to a collection of custom objects, the grid automatically generates columns for all of the object's properties according to the properties returned by the CurrencyManager. However, in this case the CurrencyManager will return an empty collection of properties, hence the grid will not create any columns (same is applicable for the .NET DataGridView as well). There are two ways to handle this:
1. In order for the CurrencyManager to return valid property descriptors, the collection holding your items should implement ITypedDescriptor. Here is a sample implementation of such collection:
Then, just bind the grid to this collection.
2. Add at least one dummy CustomItem after initializing the BindingList<CustomItem> which will initialize theCurrencyManager. Afterwards, you can clear the collection. As a result, no records will be displayed in the grid, but the Columns collection will be initialized and the new row will be shown as well.
I hope this information helps. If you have any additional questions, please let me know.
Regards,
Desislava
Telerik
Thank you for writing back.
When you bind the grid to a collection of custom objects, the grid automatically generates columns for all of the object's properties according to the properties returned by the CurrencyManager. However, in this case the CurrencyManager will return an empty collection of properties, hence the grid will not create any columns (same is applicable for the .NET DataGridView as well). There are two ways to handle this:
1. In order for the CurrencyManager to return valid property descriptors, the collection holding your items should implement ITypedDescriptor. Here is a sample implementation of such collection:
class
MyList : BindingList<CustomItem>, ITypedList
{
public
PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
{
return
TypeDescriptor.GetProperties(
typeof
(CustomItem));
}
public
string
GetListName(PropertyDescriptor[] listAccessors)
{
return
typeof
(CustomItem).Name;
}
}
Then, just bind the grid to this collection.
2. Add at least one dummy CustomItem after initializing the BindingList<CustomItem> which will initialize theCurrencyManager. Afterwards, you can clear the collection. As a result, no records will be displayed in the grid, but the Columns collection will be initialized and the new row will be shown as well.
I hope this information helps. If you have any additional questions, please let me know.
Regards,
Desislava
Telerik
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
0
Thomas
Top achievements
Rank 1
answered on 08 Oct 2014, 07:28 AM
Thanks for help. ITypedList helped in my case.