Я проверил ответы на этот вопрос: изменение свойства структуры в PropertyGrid
А также SizeConverter
от .net.
Но не полезно, моя собственность все еще не сохранена.
У меня есть структура, пользовательский элемент управления и пользовательский конвертер типов.
public partial class UserControl1 : UserControl
{
public Bar bar { get; set; } = new Bar();
}
[TypeConverter(typeof(BarConverter))]
public struct Bar
{
public string Text { get; set; }
}
public class BarConverter : ExpandableObjectConverter
{
public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
{
return true;
}
public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
{
if (propertyValues != null && propertyValues.Contains("Text"))
return new Bar { Text = (string)propertyValues["Text"] };
return new Bar();
}
}
После компиляции я перетаскиваю элемент управления в форме, затем я вижу свойство Bar.Text
показанное в окне свойств, я также могу редактировать значение, и оно кажется сохраненным.
Но ничего не генерируется в методе InitializeComponent
Поэтому, если я снова открою конструктор, поле Текст в окне свойств станет пустым.
Обратите внимание, что структура не имеет собственного конструктора, поэтому я не могу использовать InstanceDescriptor
.
Я пропускаю какие-нибудь важные шаги?
Вам не хватает нескольких переопределений методов в дескрипторе типа:
public class BarConverter : ExpandableObjectConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor))
return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context,
CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor))
{
ConstructorInfo ci = typeof(Bar).GetConstructor(new Type[] { typeof(string) });
Bar t = (Bar)value;
return new InstanceDescriptor(ci, new object[] { t.Text });
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override object CreateInstance(ITypeDescriptorContext context,
IDictionary propertyValues)
{
if (propertyValues == null)
throw new ArgumentNullException("propertyValues");
object text = propertyValues["Text"];
return new Bar((string)text);
}
public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
{
return true;
}
}
И добавьте конструктор в структуру:
[TypeConverter(typeof(BarConverter))]
public struct Bar
{
public Bar(string text)
{
Text = text;
}
public string Text { get; set; }
}
И вот как свойство Bar
сериализуется:
//
// userControl11
//
this.userControl11.Bar = new SampleWinApp.Bar("Something");
И свойство bar будет показано как следующее изображение в сетке свойств с редактируемым свойством Text
:
Вы также можете захотеть предоставить лучшее строковое представление для структуры, переопределив ее метод ToString()
структуры, а также сделайте свойство конвертируемым из строки в сетке свойств, переопределив CanConvertFrom
и ConvertFrom
такие как PointConverter
или SizeConverter
.