Click here to Skip to main content
15,921,454 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
See more:
Using VS Community 2015.

I have create a thread-safe list (TList<T>) that implements all of the standard list functionality in a thread-safe manner. I now have a user control that has a TList<ImageEntry> as a property. ImageEntry is an object derived from Component, with 3 properties. However, the CollectionEditor does not allow maintenance of this list in the designer.

The TList:
C#
public class TList<T> : IList<T>, ICollection<T>, IEnumerable<T>, IDisposable {

private ReaderWriterLockSlim _lck = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
private List<T> _list = new List<T>();
private bool _lockableEnumerator = false;

public TList() { }
public TList(bool lockableEnumerator) : base() {
	_lockableEnumerator = lockableEnumerator;
}
public TList(IEnumerable<T> elements, bool lockableEnumerator = false) {
	_list.AddRange(elements);
	_lockableEnumerator = lockableEnumerator;
}
.... // All the list functionality here
}

The contents:
C#
[DesignTimeVisible(false)]
public class ImageEntry : Component { 
	protected Bitmap _image = null;
	protected string _path = null;
	ImageDrawMode _sizemode = ImageDrawMode.Zoom;

	public ImageEntry() { }

	[DefaultValue(typeof(Bitmap), null)]
	public virtual Bitmap Image {
		get {
			if (_image == null) {
				if (!string.IsNullOrEmpty(_path))
					_image = new Bitmap(_path);
			}
			return _image;
		}
		set {
			_image = value;
			if (value != null)
				_path = null;
		}
	}
	[DefaultValue(typeof(string), "")]
	public virtual string Path {
		get { return _path ?? string.Empty; }
		set {
			if (string.IsNullOrEmpty(value))
				_path = null;
			else {
				_image = null;
				_path = value;
			}
		}
	}
	[DefaultValue(ImageDrawMode.Zoom)]
	public virtual ImageDrawMode SizeMode {
		get {
			return _sizemode;
		}
		set {
			_sizemode = value;
		}
	}
	public override string ToString() {
		return string.IsNullOrEmpty(_path) ? ((_image == null) ? null : _image.ToString()) : _path;
	}
}

The property:
C#
TList<ImageEntry> _images = new TList<ImageEntry>();
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Description("The collection of images to cycle through")]
[Category("Effects")]
[Editor(typeof(CollectionEditor), typeof(UITypeEditor))]
public TList<ImageEntry> Images {
	get { return _images; }
}


When I bring up the CollectionEditor in the IDE, it does not show the ImageEntry properties on the right, and the Add and Remove buttons are disabled on the left. However, if I modify the Images property such that it returns the internal List<ImageEntry>, it all works fine (but then, of course, my Images property is not thread-safe).

I have tried putting together a custom Collection editor, but that didn't work either.
C#
public class ImageEntryCollectionEditor : CollectionEditor {
	public ImageEntryCollectionEditor(Type type) : base(type) { }
	protected override Type[] CreateNewItemTypes() {
		return new Type[] { typeof(ImageEntry) };
	}
	protected override Type CreateCollectionItemType() {
		return typeof(ImageEntry);
	}
}


What am I missing here?
Posted

It can be tricky to get the UITypeEditor to work well with custom collections.
I think this CP article can help you.
How to Edit and Persist Collections with CollectionEditor[^]

This is another CP article I have used myself Customized display of collection data in a PropertyGrid[^]

This MSDN article can also be helpful, if you haven't seen it already. Walkthrough: Implementing a UI Type Editor[^]
 
Share this answer
 
Comments
BillWoodruff 15-Nov-15 1:46am    
+5
George Jonsson 15-Nov-15 1:55am    
Thanks Bill.
Midi_Mick 15-Nov-15 1:54am    
Thanks for those suggestions/links George. I already looked at that first article, and that got me as far as I had gotten. Read the other two since, and not really a lot of help there, either (as they all seem to used standard collection objects). So I started looking down the line at what those standard collections exposed that I didn't - which gave me my solution below.
George Jonsson 15-Nov-15 1:57am    
Good that you found a solution.
Maybe you could write your own tip here on CP and share the knowledge.
Midi_Mick 15-Nov-15 4:03am    
Absolutely! :)
I've got it - I needed to also implement the non-generic IList interface on the collection. As soon as I did that, everything just worked.
 
Share this answer
 
Comments
BillWoodruff 15-Nov-15 13:05pm    
+5 Glad to hear you got it solved, Midi_Mick; I second George's suggestion you publish a tip-trick here on CP. Getting custom-collection editable in the property browser is a tricky piece of work in WinForms, and I, and I am sure others, will benefit form your work.
Midi_Mick 15-Nov-15 19:32pm    
Tip/Trick submitted - I'll post a link to it in here once it is published.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900