属性 在 VS .NET 自定义组件中将样式编辑为 DropDown
Property edit style as DropDown in a VS .NET custom component
我想使用 ComboBox 的功能作为自定义控件/组件属性 window 中 var 的编辑选项。不是 ComboBox 组件本身。
例如:
private string[] _stringArray = { "string0", "string1" };
public string[] StringArray
{
get { return _stringArray; }
//callback
//set { _stringArray = value; }
}
如您所知,这将给我对象浏览器作为 属性 window 中的 view/edit 选项。
有趣的是,即使没有 setter.
我也可以编辑这些值
在我的研究中,我发现这是可能的 ("UITypeEditorEditStyle.DropDown")。但我不知道如何实施。
或者我可以为“StringArray”设置什么[说明]。
我的最终目标是将 visual studio 的对象选择器下拉列表复制为 属性 参数:
当然是自定义事件处理。但正如你所见,我离意识到这一点还很遥远。 :(
我一直在寻找关于以下主题的教程:
- [设计师]说明参考
属性显示样式管理基础教程✔
但是我厌倦了我不成功的研究。一些好的链接总是受欢迎的。
更新:
大概明白原理后(来自评论中的link,谢谢),我得出了一个临时解决方案。
我意识到我至少需要一个 int var 来设置选定的“索引”。我以为/希望 VS 可以自动执行此操作。就像枚举一样。我对[说明]缺乏了解。
我可以将一个字符串变量定义为数组选定索引的占位符,以便在没有 TypeConverter 的情况下进行操作,但这更没有意义。我真的不需要另一个抽象变量。
所以基础下拉,例如可以直接显示枚举,貌似不适用。所以他们使用 "UITypeEditorEditStyle.DropDown" 的技巧,这实际上不是下拉菜单。它只是一个按钮,您可以在其中放置您选择的控件。在我的例子中是一个 ListView。由于 "down" 的 "drop" 已经存在。看起来像作弊。 ;)
//...
[TypeConverter(typeof(StringArrayConverter))]
public interface IStringArray
{
int SelectedIndex { get; set; }
string[] StringArray { get; set; }
}
public class DropDownStringArray : IStringArray
{
private string[] _stringArray = { "string0", "string1", "string2", "string3", "string4", "string5", "string6" };
public int SelectedIndex { get; set; }
public string[] StringArray
{
get { return _stringArray; }
set { _stringArray = value; }
}
}
private DropDownStringArray _ddsa = new DropDownStringArray();
[Editor(typeof(StringArrayTypeEditor), typeof(UITypeEditor))]
public DropDownStringArray MyDropDownStringArray
{
get { return _ddsa; }
set { _ddsa = value; }
}
//...
public class StringArrayConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
var sa = value as IStringArray;
if (sa != null) { return sa.StringArray[sa.SelectedIndex]; }
}
return "(none)";
}
}
public class StringArrayTypeEditor : UITypeEditor
{
private IWindowsFormsEditorService _editorService;
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.DropDown; }
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
_editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
DropDownStringArray ddsa = (DropDownStringArray)value;
ListBox lb = new ListBox();
lb.SelectionMode = SelectionMode.One;
for (int i = 0; i < ddsa.StringArray.Length; i++) { lb.Items.Add(ddsa.StringArray[i]); }
lb.SetSelected(ddsa.SelectedIndex, true);
lb.SelectedValueChanged += OnListBoxSelectedValueChanged;
_editorService.DropDownControl(lb);
if (lb.SelectedItem != null) { ddsa.SelectedIndex = lb.SelectedIndex; }
return value;
}
private void OnListBoxSelectedValueChanged(object sender, EventArgs e)
{
_editorService.CloseDropDown();
}
}
其中实际上复制了整个class只是为了改变SelectedIndex
。正确的做法是滥用 SelectedIndex 并将其转换为字符串或类似的东西。我想我不再关心那个了。而是去呼吸新鲜空气。 ;)
也许这会对其他人有所帮助。
注意:这不是一个实际的提议。例如,如果更改数组的(长度), SelectedIndex 将不会更新。我选择了 string[] 因为它是一个非常基本且众所周知的类型。我知道我的“程序”没有实际用处。只是理解了原理。
我想使用 ComboBox 的功能作为自定义控件/组件属性 window 中 var 的编辑选项。不是 ComboBox 组件本身。
例如:
private string[] _stringArray = { "string0", "string1" };
public string[] StringArray
{
get { return _stringArray; }
//callback
//set { _stringArray = value; }
}
如您所知,这将给我对象浏览器作为 属性 window 中的 view/edit 选项。 有趣的是,即使没有 setter.
我也可以编辑这些值在我的研究中,我发现这是可能的 ("UITypeEditorEditStyle.DropDown")。但我不知道如何实施。 或者我可以为“StringArray”设置什么[说明]。
我的最终目标是将 visual studio 的对象选择器下拉列表复制为 属性 参数:
当然是自定义事件处理。但正如你所见,我离意识到这一点还很遥远。 :(
我一直在寻找关于以下主题的教程:
- [设计师]说明参考
属性显示样式管理基础教程✔
但是我厌倦了我不成功的研究。一些好的链接总是受欢迎的。
更新:
大概明白原理后(来自评论中的link,谢谢),我得出了一个临时解决方案。 我意识到我至少需要一个 int var 来设置选定的“索引”。我以为/希望 VS 可以自动执行此操作。就像枚举一样。我对[说明]缺乏了解。
我可以将一个字符串变量定义为数组选定索引的占位符,以便在没有 TypeConverter 的情况下进行操作,但这更没有意义。我真的不需要另一个抽象变量。
所以基础下拉,例如可以直接显示枚举,貌似不适用。所以他们使用 "UITypeEditorEditStyle.DropDown" 的技巧,这实际上不是下拉菜单。它只是一个按钮,您可以在其中放置您选择的控件。在我的例子中是一个 ListView。由于 "down" 的 "drop" 已经存在。看起来像作弊。 ;)
//...
[TypeConverter(typeof(StringArrayConverter))]
public interface IStringArray
{
int SelectedIndex { get; set; }
string[] StringArray { get; set; }
}
public class DropDownStringArray : IStringArray
{
private string[] _stringArray = { "string0", "string1", "string2", "string3", "string4", "string5", "string6" };
public int SelectedIndex { get; set; }
public string[] StringArray
{
get { return _stringArray; }
set { _stringArray = value; }
}
}
private DropDownStringArray _ddsa = new DropDownStringArray();
[Editor(typeof(StringArrayTypeEditor), typeof(UITypeEditor))]
public DropDownStringArray MyDropDownStringArray
{
get { return _ddsa; }
set { _ddsa = value; }
}
//...
public class StringArrayConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
var sa = value as IStringArray;
if (sa != null) { return sa.StringArray[sa.SelectedIndex]; }
}
return "(none)";
}
}
public class StringArrayTypeEditor : UITypeEditor
{
private IWindowsFormsEditorService _editorService;
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.DropDown; }
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
_editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
DropDownStringArray ddsa = (DropDownStringArray)value;
ListBox lb = new ListBox();
lb.SelectionMode = SelectionMode.One;
for (int i = 0; i < ddsa.StringArray.Length; i++) { lb.Items.Add(ddsa.StringArray[i]); }
lb.SetSelected(ddsa.SelectedIndex, true);
lb.SelectedValueChanged += OnListBoxSelectedValueChanged;
_editorService.DropDownControl(lb);
if (lb.SelectedItem != null) { ddsa.SelectedIndex = lb.SelectedIndex; }
return value;
}
private void OnListBoxSelectedValueChanged(object sender, EventArgs e)
{
_editorService.CloseDropDown();
}
}
其中实际上复制了整个class只是为了改变SelectedIndex
。正确的做法是滥用 SelectedIndex 并将其转换为字符串或类似的东西。我想我不再关心那个了。而是去呼吸新鲜空气。 ;)
也许这会对其他人有所帮助。
注意:这不是一个实际的提议。例如,如果更改数组的(长度), SelectedIndex 将不会更新。我选择了 string[] 因为它是一个非常基本且众所周知的类型。我知道我的“程序”没有实际用处。只是理解了原理。