我正在为visual studio开发一个扩展程序。
我有一个选项页面:
public class GeneralOptionsPage : DialogPage
{
[Category("General")]
[DisplayName("Foos")]
[Description("Bla Foo Bla")]
public string[] Foos { get; set; }
[Category("General")]
[DisplayName("Bar")]
[Description("Bar Foo Bar")]
public string Bar { get; set; }
}
Bar
属性可以完美运行并保持不变。
Foos
属性也可以工作(它甚至可以在选项页面为你提供一个很好的弹出窗口,你可以在每行输入一个字符串),这意味着我可以设置它并在我的扩展中使用它但是它没有写入注册表/存储。当我关闭VS并再次打开它时,它总是空着的。
引自MSDN:
DialogPage的默认实现支持具有适当转换器的属性,或者是可以扩展为具有适当转换器的属性的结构或数组的属性。有关转换器列表,请参阅System.ComponentModel命名空间。 Visual Studio Extensibility Samples管理int,string和System.Drawing.Size属性。
据我所知,我正在使用System.ComponentModel
命名空间中的有效组件。
那么我做错了什么?我是否必须以不同的方式处理数组?
答案 0 :(得分:6)
您需要为Foos属性实现并关联自定义TypeConverter。
没有库存转换器可以覆盖这种情况,因为当您将字符串数组转换为字符串时,您必须具有某种分隔符,因此您可以从字符串重构数组。这取决于各个程序员的应用程序。因此需要自定义TypeConverter。
因此,您必须从System.ComponentModel.TypeConverter派生一个新类,然后将其与您的Foos属性关联。例如:
[Category("General")]
[DisplayName("Foos")]
[Description("Bla Foo Bla")]
[TypeConverter(typeof(FoosCoverter))]
public string[] Foos { get; set; }
快速互联网搜索应该提供一些示例,让您指出正确的方向。
DialogPage.SaveSettingsToStorage循环遍历页面PropertyDescriptors的集合,检索每个属性的转换器,调用CanConvertTo和CanConvertFrom以确保属性可以转换为字符串/从字符串转换,然后调用转换器& #39;使用ConvertToInvariantString将属性保存到注册表值。
相反,DialogPage.LoadSettingsfromStorage循环遍历注册表值,找到与DialogPage上的属性匹配的PropertyDescriptor,检索其Coverter,然后调用CanCovertFrom以确保该字符串可以转换回该特定属性类型,然后调用转换器的ConvertFromIvariantString,然后将值赋给该属性。
答案 1 :(得分:5)
Ed Dore提供正确的答案(谢谢)。
我的自定义TypeConverter
:
class StringArrayConverter : TypeConverter
{
private const string delimiter = "#@#";
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string[]) || base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
string v = value as string;
return v == null ? base.ConvertFrom(context,culture,value) : v.Split(new[] {delimiter}, StringSplitOptions.RemoveEmptyEntries);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
string[] v = value as string[];
if (destinationType != typeof(string) || v == null)
{
return base.ConvertTo(context, culture, value,destinationType);
}
return string.Join(delimiter, v);
}
}