问题描述
我想在自定义控件/组件的属性窗口中使用 ComboBox 的功能作为 var 的编辑选项.不是 ComboBox 组件本身.
I'd like to use the functionality of a ComboBox as edit option for a var in the properties window of a custom control / component. Not the ComboBox component itself.
例如:
private string[] _stringArray = { "string0", "string1" };
public string[] StringArray
{
get { return _stringArray; }
//callback
//set { _stringArray = value; }
}
如您所知,这将为我提供对象浏览器作为属性窗口中的查看/编辑选项.有趣的是,即使没有 setter,我也可以编辑值.
As you know this will give me the object browser as view/edit option in the property window. Funny thing that I can edit the values even with no setter.
在我的研究中,我发现这是可能的(UITypeEditorEditStyle.DropDown").但我不知道如何实现.或者我可以为StringArray"设置什么[指令].
In my researches I found out that it is possible ("UITypeEditorEditStyle.DropDown"). But I have no idea how to implement that. Or what [Instructions] I could set for the "StringArray".
我的最终目标是复制visual studio的对象选择器下拉菜单作为属性参数:
My final goal is a copy of the object selector drop-down of visual studio as a property parameter:
当然是自定义事件处理.但正如你所见,我离实现这一点还很遥远.:(
我一直在寻找有关以下主题的教程:
With custom event handling of course. But as you see I'm far away to realize that. :(
I have been looking for a tutorial on the following topics for a long time:
- [Designer] 说明参考
管理属性显示样式的基础教程✔
但是我厌倦了我不成功的研究.一些好的链接总是受欢迎的.
However I'm tired of my unsuccessful researches. Some good links are always welcome.
推荐答案
更新:
在我或多或少地理解了原理之后(来自评论中的链接,谢谢),我找到了一个临时解决方案.我意识到我至少需要一个 int var 来设置选定的索引".我认为/希望 VS 可以自动执行此操作.就像枚举一样.我对[指令]缺乏了解.
我可以将字符串变量定义为数组的选定索引的占位符,以便在没有 TypeConverter 的情况下进行,但这更没有意义.我真的不需要另一个抽象变量.
所以基础下拉,例如可以直接显示枚举,貌似不适用.所以他们使用UITypeEditorEditStyle.DropDown"的技巧,这实际上不是下拉菜单.它只是一个按钮,您可以在其中放置您选择的控件.在我的例子中是一个 ListView.由于下降"的下降"已经存在.看起来像作弊.;)
UPDATE:
After I more or less understood the principle (from the link in the comments, thanks) I came to an interim solution.
I realized that I need at least an int var to set a selected `index`. I thought / hoped that VS can do this automatically. Like it does with enums. And my lack of knowledge concerning [Instructions].
I could define a string variable as a placeholder for the selected index of the array in order to do without the TypeConverter, but that would make even less sense. I really don't need another abstract variable for nothing.
So the basis drop-down, which e.g. can display enums directly, does not appear to be applicable. So they use a trick with "UITypeEditorEditStyle.DropDown", which actually isn't a drop-down. It's just a button where you can place the control of your choice. In my case a ListView. Since the "drop" of the "down" already exists. Looks like cheating. ;)
//...
[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();
}
}
实际上复制整个类只是为了更改SelectedIndex
.正确的做法是滥用 SelectedIndex 并将其转换为字符串或类似的东西.我想我不再关心这个了.而是去呼吸新鲜空气.;)
Which actually copy the entire class just to change the SelectedIndex
. The right thing would be to abuse the SelectedIndex and convert it to a string or something like that. I think I do not care about that anymore. Rather to catch some fresh air. ;)
也许这会对其他人有所帮助.
Maybe that will help someone else.
注意:这不是一个实际的建议.例如,如果您更改数组的(长度),则不会更新 SelectedIndex.我选择了 string[] 因为它是一个非常基本且众所周知的类型.我知道我的程序"没有实际用处.这只是关于理解原理.
Note: This is not a practical propose. As example SelectedIndex will not be updated if you change the (length) of the array. I've choosen string[] because it's a really basic and well known type. I am aware that my "program" has no real use. It was just about understanding the principle.
这篇关于VS .NET 自定义组件中的属性编辑样式为 DropDown的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!