I am displaying a Collection as an expandable object. I only have the options of sorting alphabetically, or not at all.
Alphabetically turns out as such:
No Sort turns out as such:
I am trying to find a way to sort the collection by index, so it will look like
[0], [1], [2], [3], ..., [9], [10], [11], [12], [13], [14].
I haven't been able to find a reliable way to do this.
I did find a solution here, but they use ListItemDescriptor
, which doesn't seem to exist.
This is my customertypeconverter, how I have the collection in the object that is in the propertygrid, and the customeditor.
The custom editor just forces it to be expandable only, instead of giving the user the option to open the default editor and add more items.
This is for UserData instead of MarkData, I have done all the work towards UserData, but I used the images for MarkData because it is a smaller collection and made for easier images.
internal class UserDataCollectionConverter : ExpandableObjectConverter
{
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destType)
{
if (destType == typeof(string) && value is UserDataCollection)
{
return "User Data";
}
return base.ConvertTo(context, culture, value, destType);
}
}
Object
[EditorAttribute(typeof(UserDataEditor), typeof(UITypeEditor))]
[DescriptionAttribute("Custom user data."),
TypeConverter(typeof(UserDataCollectionConverter)),
CategoryAttribute("Custom")]
public UserDataCollection UserData
{
get { return _userData; }
set { _userData = value; }
}
Custom Editor
class UserDataEditor : System.ComponentModel.Design.CollectionEditor
{
public UserDataEditor(Type type)
: base(type)
{
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
UserDataCollection things = new UserDataCollection();
return value;
}
}
UserDataCollection
using System;
using System.Collections;
using System.ComponentModel;
namespace CMS.LaserGraf.Data
{
public class UserDataCollection : CollectionBase, ICustomTypeDescriptor
{
#region
public void Add(string value)
{
this.List.Add(value);
}
public void Add(int number)
{
for (int i = 0; i < number; i++)
{
this.List.Add("");
}
}
public void Remove(string value)
{
this.List.Remove(value);
}
public void set(string[] values)
{
this.List.Clear();
foreach (string s in values)
{
this.List.Add(s);
}
}
public string[] getUserDataArray()
{
int i = 0;
string[] retval = new string[this.List.Count];
foreach (string s in this.List)
{
retval[i++] = s;
}
return retval;
}
public string this[int index]
{
get
{
return (string)this.List[index];
}
set
{
this.List[index] = value;
}
}
#endregion
// Implementation of interface ICustomTypeDescriptor
#region ICustomTypeDescriptor impl
public String GetClassName()
{
return TypeDescriptor.GetClassName(this, true);
}
public AttributeCollection GetAttributes()
{
return TypeDescriptor.GetAttributes(this, true);
}
public String GetComponentName()
{
return TypeDescriptor.GetComponentName(this, true);
}
public TypeConverter GetConverter()
{
return TypeDescriptor.GetConverter(this, true);
}
public EventDescriptor GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(this, true);
}
public PropertyDescriptor GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(this, true);
}
public object GetEditor(Type editorBaseType)
{
return TypeDescriptor.GetEditor(this, editorBaseType, true);
}
public EventDescriptorCollection GetEvents(Attribute[] attributes)
{
return TypeDescriptor.GetEvents(this, attributes, true);
}
public EventDescriptorCollection GetEvents()
{
return TypeDescriptor.GetEvents(this, true);
}
public object GetPropertyOwner(PropertyDescriptor pd)
{
return this;
}
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return GetProperties();
}
public PropertyDescriptorCollection GetProperties()
{
// Create a collection object to hold property descriptors
PropertyDescriptorCollection pds = new PropertyDescriptorCollection(null);
// Iterate the list of ProcessCounters
for (int i = 0; i < this.List.Count; i++)
{
// Create a property descriptor for the ProcessCounter item and add to the property descriptor collection
UserDataCollectionPropertyDescriptor pd = new UserDataCollectionPropertyDescriptor(this, i);
pds.Add(pd);
}
// return the property descriptor collection
return pds;
}
#endregion
}
}
It seems you are already adding in a specific order as seen in below code
// Iterate the list of ProcessCounters
for (int i = 0; i < this.List.Count; i++)
{
// Create a property descriptor for the ProcessCounter item and add to the property descriptor collection
UserDataCollectionPropertyDescriptor pd = new UserDataCollectionPropertyDescriptor(this, i);
pds.Add(pd);
}
You could achieve sorting in two ways.
UserDataCollectionPropertyDescriptor
while adding into the PropertyDescriptorCollection
in GetProperties()
method.PropertyDescriptorCollection
class and override the Sort(IComparer comparer)
method and pass in your custom comparer for comparing UserDataCollectionPropertyDescriptor
.Sample Code
public class UserDataPropertyDescriptorCollection : PropertyDescriptorCollection
{
public override PropertyDescriptorCollection Sort(IComparer comparer)
{
UserDataComparer customComparer = new UserDataComparer();
return base.Sort(customComparer);
}
}
public class UserDataComparer : IComparer
{
#region IComparer Members
int IComparer.Compare(object x, object y)
{
//cast and compare UserDataCollectionPropertyDescriptor index values
}
#endregion
}