Categories are not shown in PropertyGrid for a collection<T>, when all the properties of <T> are read-only

  • A+

As the title says, I noticed that the categories are not shown in a **PropertyGrid* (in its default collection editor) for a collection(Of T), when all the properties of class "T" are read-only.

The code below represents the code structure I have:


[TypeConverter(typeof(ExpandableObjectConverter))] public class TestClass1 {      public TestClass2 TestProperty1 {get;} = new TestClass2(); }  [TypeConverter(typeof(ExpandableObjectConverter))] public sealed class TestClass2 {      [TypeConverter(typeof(CollectionConverter))]     public ReadOnlyCollection<TestClass3> TestProperty2 {         get {             List<TestClass3> collection = new List<TestClass3>();             for (int i = 0; i <= 10; i++) {                 collection.Add(new TestClass3());             }             return collection.AsReadOnly();         }     } }  [TypeConverter(typeof(ExpandableObjectConverter))] public sealed class TestClass3 {      [Category("Category 1")]     public string TestProperty3 {get;} = "Test"; } 


<TypeConverter(GetType(ExpandableObjectConverter))> Public Class TestClass1      Public ReadOnly Property TestProperty1 As TestClass2 = New TestClass2()  End Class  <TypeConverter(GetType(ExpandableObjectConverter))> Public NotInheritable Class TestClass2      <TypeConverter(GetType(CollectionConverter))>     Public ReadOnly Property TestProperty2 As ReadOnlyCollection(Of TestClass3)         Get             Dim collection As New List(Of TestClass3)             For i As Integer = 0 To 10                 collection.Add(New TestClass3())             Next             Return collection.AsReadOnly()         End Get     End Property  End Class  <TypeConverter(GetType(ExpandableObjectConverter))> Public NotInheritable Class TestClass3      <Category("Category 1")>     Public ReadOnly Property TestProperty3 As String = "Test"  End Class 

The problem is with TestProperty3. When it is read-only, the category ("Category 1") is not shown in the property grid...

Categories are not shown in PropertyGrid for a collection<T>, when all the properties of <T> are read-only

But if I do the property editable, then the category is shown...


[Category("Category 1")] public string TestProperty3 {get; set;} = "Test"; 


<Category("Category 1")> Public Property TestProperty3 As String = "Test" 

Categories are not shown in PropertyGrid for a collection<T>, when all the properties of <T> are read-only

More than that, let's imagine that in TestClass3 are declared 10 properties (instead of 1 like in this example), and 9 of them are read-only, and 1 is editable, then, in this circumstances all the categories will be shown. On the other side, if all the 10 properties are read-only, then categories will not be shown.

This behavior of the PeopertyGrid is very annoying and unexpected for me. I would like to see my custom categories regardless of whether in my class are declared properties with a setter or without it.

What alternatives I have to show categories having all the properties of my class read-only?. Maybe writing a custom TypeConverter or collection editor could fix this annoying visual representation behavior?.


That is indeed a very annoying behaviour. However, I don't believe you can get around it: it isn't the property-descriptor that is at fault - it is reporting the correct category - as you can validate via:

var props = TypeDescriptor.GetProperties(new TestClass3()); foreach(PropertyDescriptor prop in props) {     Console.WriteLine($"{prop.Category}: {prop.Name}"); } 

which outputs Category 1: TestProperty3.

So; this is simply a quirk of the collection editor UI control . Oddly, if you add a second writable property, it starts displaying the category for both. But if you add a second read-only property: it doesn't display the category. This applies both for get-only properties, and properties marked [ReadOnly(true)].

So: I don't think there's a good solution here, except perhaps to use a different property-grid implementation, or to add a dummy writable property - sorry!

As a side/unrelated note: when using the {get;set;} = "initial value"; style initialization (or constructor initialization), it is a good idea to also add [DefaultValue("initial value")] to that property, so that it gets the ShouldSerialize*() behaviour correct (or in PropertyGrid terms: so that it is bold / not-bold appropriately), but... this won't fix the problem you're seeing, sorry.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: