【问题标题】:Property edit style as DropDown in a VS .NET custom componentVS .NET 自定义组件中的属性编辑样式为 DropDown
【发布时间】:2020-10-25 23:52:04
【问题描述】:

我想在自定义控件/组件的属性窗口中使用 ComboBox 的功能作为 var 的编辑选项。不是 ComboBox 组件本身。

例如:

private string[] _stringArray = { "string0", "string1" };
public string[] StringArray
{
    get { return _stringArray; }
    //callback
    //set { _stringArray = value; }
}

如您所知,这将为我提供对象浏览器作为属性窗口中的查看/编辑选项。 有趣的是,即使没有 setter,我也可以编辑值。

在我的研究中,我发现这是可能的(“UITypeEditorEditStyle.DropDown”)。但我不知道如何实现。 或者我可以为“StringArray”设置什么[指令]。

我的最终目标是复制visual studio的对象选择器下拉菜单作为属性参数:

当然是自定义事件处理。但正如你所见,我离实现这一点还很遥远。 :(

我一直在寻找关于以下主题的教程:

  • [Designer] 说明参考
  • 管理属性显示样式的基础教程

但是我厌倦了我不成功的研究。一些好的链接总是受欢迎的。

【问题讨论】:

  • 您可以从stackoverflow.com/q/5171037/1070452 开始,这里有几十个详细答案; MSDN/MS Docs 也有一些教程和权威文章。字符串数组是一个奇怪的选择,但如果它不是“可设置”的,请考虑一个枚举,在这种情况下,TypeConverter 将起作用。
  • string[] 只是 ComboBox Lines 的默认类型,这就是为什么我选择该类型作为示例...
  • ComboBox 为 Items Collection 使用 ObjectCollection - 您可以在其中存储几乎任何内容,而不是字符串数组。它不仅仅是您所追求的“展示风格”。有些人将使用自定义 UITypeEditor,但这仅适用于设计时的属性窗格。有些人会使用TypeConverterStandardValues 功能,该功能为UI 提供了道具窗格的列表。此处和 MS Docs 中也有大量详细信息。
  • 知道了。也许我的问题是信息的“溢出”。 ;) 使用枚举,我默认得到一个 dd ,好的。我觉得你的链接很好。不知道为什么我自己找不到这样的页面。谢谢。我会通过 TypeConverter 的事情。这只是..啊,不可能那么难。但它是(对我来说)。

标签: c# visual-studio-2010 user-controls designer design-time


【解决方案1】:

更新:

在我或多或少地理解了原理之后(来自 cmets 中的链接,谢谢),我找到了一个临时解决方案。 我意识到我至少需要一个 int var 来设置选定的“索引”。我认为/希望 VS 可以自动执行此操作。就像枚举一样。我对[指令]缺乏了解。

我可以将字符串变量定义为数组的选定索引的占位符,以便在没有 TypeConverter 的情况下进行,但这更没有意义。我真的不需要另一个抽象变量。

所以基础下拉,例如可以直接显示枚举,貌似不适用。所以他们使用“UITypeEditorEditStyle.DropDown”的技巧,这实际上不是下拉菜单。它只是一个按钮,您可以在其中放置您选择的控件。在我的例子中是一个 ListView。由于“下降”的“下降”已经存在。看起来像作弊。 ;)

//...
 
[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 并将其转换为字符串或类似的东西。我想我不再关心这个了。而是去呼吸新鲜空气。 ;)

也许这会对其他人有所帮助。

注意:这不是一个实际的建议。例如,如果您更改数组的(长度),则不会更新 SelectedIndex。我选择了 string[] 因为它是一个非常基本且众所周知的类型。我知道我的“程序”没有真正的用处。这只是关于理解原理。

【讨论】:

  • 您的代码有效。由于我目前在我的自定义组件中需要一个可以提供像组合框这样的选择的属性,因此我正在尝试使用此代码。我仍然面临的一个问题是如何知道何时选择了一个值。换句话说,有人从列表中选择了一个值,例如 string3`,那么我怎样才能得到通知呢?
猜你喜欢
  • 2013-12-13
  • 2019-11-17
  • 2015-01-23
  • 1970-01-01
  • 2011-09-20
  • 1970-01-01
  • 2016-11-30
  • 2022-07-13
  • 1970-01-01
相关资源
最近更新 更多