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:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Editor(typeof(FileTypeEditor), typeof(UITypeEditor))]
public FileTypes FileTypes { get; internal set; } = new FileTypes();
The collection item:
[Serializable]
[TypeConverter(typeof(FileTypeConverter))]
public class FileType {
internal FileType() { }
public FileType(string description, string filter) {
Description = description; Filter = filter;
}
The
TypeConverter
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
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:
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.