Click here to Skip to main content
15,887,945 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have created a property which is a collection of objects, with a custom UITypeEditor for the collection, and a TypeConverter for the objects. All seems to be working OK except if I go in and edit the collection in the designer for a 2nd or subsequent time, the new values of the collection are not being initialised.

I think the important bits of my code are:
The collection property:
C#
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Editor(typeof(FileTypeEditor), typeof(UITypeEditor))]
public FileTypes FileTypes { get; internal set; } = new FileTypes();

The collection item:
C#
[Serializable]
[TypeConverter(typeof(FileTypeConverter))]
public class FileType  {
	internal FileType() { }
	public FileType(string description, string filter) { 
		Description = description; Filter = filter; 
	}
	// ...

The TypeConverter
C#
class FileTypeConverter : TypeConverter {
	static Regex srch = new Regex(@"^(.*)\s\((.*)\)$", RegexOptions.Compiled);
	public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) {
		if (sourceType == typeof(string))
			return true;
		return base.CanConvertFrom(context, sourceType);
	}
	public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) {
		if (destinationType == typeof(string) || destinationType == typeof(InstanceDescriptor))
			return true;
		return base.CanConvertTo(context, destinationType);
	}
	public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
		if (value is string) {
			try {
				Match m = srch.Match((string)value);
				return new FileType(m.Groups[1].Value, m.Groups[2].Value);
			}
			catch {
				return new FileType();
			}
		}
		return base.ConvertFrom(context, culture, value);
	}
	public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
		if (value is FileType) {
			FileType ft = (FileType)value;
			if (destinationType == typeof(string)) {
				return $"{ft.Description} ({ft.Filter})";
			}
			if (destinationType == typeof(InstanceDescriptor)) {
				return new InstanceDescriptor(typeof(FileType).GetConstructor(new[] { typeof(string), typeof(string) }), new object[] { ft.Description, ft.Filter });
			}
		}
		return base.ConvertTo(context, culture, value, destinationType);
	}
}

The UITypeEditor
C#
public class FileTypeEditor : UITypeEditor {
	IWindowsFormsEditorService _editorService;

	public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
		return UITypeEditorEditStyle.Modal;
	}
	public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
		if (provider != null) {
			_editorService = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;

			if (_editorService != null) {
				using (FileTypeEditorForm frm = new FileTypeEditorForm((FileTypes)value, _editorService)) {
					if (_editorService.ShowDialog(frm) == DialogResult.OK) {
						return frm.FileTypes;
					}
				}
			}
		}
		return value;
	}
}

The generated initialisation code after the property is edited the first time:
C#
this.fileOpenDialog1.FileTypes.AddRange(new CommonItemDialog.FileType[] { 
	new CommonItemDialog.FileType("All Files", "*.*"),
	new CommonItemDialog.FileType("Audio Files", "*.m4a;*.mp3;*.wav;*.wma")});

Which is all perfect. This only issue is if I go and change the collection - add a new item, or change an item, this initialisation does not change to reflect the edited collection.
What am I missing here? I'm at my wit's end.

What I have tried:

Searching google, reading tonnes of articles (including, but not limited to CP here[^] and here[^]) - I just can't see what I'm missing here.
Posted
Comments
Midi_Mick 15-Oct-16 13:35pm    
Well, I've worked around the issue, by making the collection an array, and doing standard serialization (I got rid of the TypeConverter altogether). Would still very much like to know why the structure I was using was failing, though.

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