Click here to Skip to main content
15,897,704 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

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.
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! :)

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