ComboBox 自动 DropDownWidth 与 DataSource 类型无关

Posted

技术标签:

【中文标题】ComboBox 自动 DropDownWidth 与 DataSource 类型无关【英文标题】:ComboBox auto DropDownWidth regardless of DataSource type 【发布时间】:2021-11-19 18:54:47 【问题描述】:

我想根据下拉项目中最长的字符串调整任何ComboBox 下拉菜单的宽度。我希望这适用于任何带有项目的ComboBox,这意味着项目是字符串的对象、带有DisplayMember 集合的对象或DataTable。我 found some code 适用于字符串,但不适用于设置 DisplayMember

static void resizeCombo(ComboBox cb)

    cb.DropDownWidth = cb.Items.Cast<string>().Max(x => TextRenderer.MeasureText(x, cb.Font).Width);

在以下三个示例中,第一个只是字符串的示例将起作用,但以下两个不起作用(cb.Items.Cast&lt;string&gt;() 转换为字符串失败),并证明 DisplayMember 在绑定到不同类的源时会有所不同,所以我不能只使用“名称”,例如

var c = new string[]  "Name1", "Name2" ;
comboBox.DataSource = c.ToList();
resizeCombo(comboBox);

var c1 = new Class1[]  new Class1()  ID = 1, Name1 = "Name1" , new Class1()  ID = 2, Name1 = "Name2"  ;
comboBox1.DisplayMember = "Name1";
comboBox1.ValueMember = "ID";
comboBox1.DataSource = c1.ToList();
resizeCombo(comboBox1);

var c2 = new Class2[]  new Class2()  ID = 2, Name2 = "Name1" , new Class2()  ID = 2, Name2 = "Name2"  ;
comboBox2.DisplayMember = "Name2";
comboBox2.ValueMember = "ID";
comboBox2.DataSource = c2.ToList();
resizeCombo(comboBox2);

我可以反映DisplayMember,并按名称查找字符串,它可以解决List&lt;class&gt; 的情况,但不能解决DataTable

我正在寻找一种方法来获取ComboBox 中的所有字符串,无论它们是如何添加的。有吗?

【问题讨论】:

【参考方案1】:

Combobox 有GetItemText 方法,该方法返回项目的字符串表示形式。

这应该可行:

    static void resizeCombo(ComboBox cb)
    
        if (cb.Items.Count == 0) cb.DropDownWidth = cb.Width;
        else
        
            int maxWidth = int.MinValue;
            for (int i = 0; i < cb.Items.Count; i++)
            
                maxWidth = Math.Max(maxWidth, TextRenderer.MeasureText(cb.GetItemText(cb.Items[i]), cb.Font).Width);
            
            if (cb.Items.Count > cb.MaxDropDownItems) maxWidth += SystemInformation.VerticalScrollBarWidth                    
            cb.DropDownWidth = maxWidth;
        
    

使用 DataTable 进行测试:

        DataTable t = new DataTable();
        t.Columns.Add(new DataColumn("ID", typeof(int)));
        t.Columns.Add(new DataColumn("Name2", typeof(string)));

        t.Rows.Add(new object[]  1, "Somename" );
        t.Rows.Add(new object[]  2, "Some other name" );

        comboBox2.DisplayMember = "Name2";
        comboBox2.ValueMember = "ID";
        comboBox2.DataSource = t;
        resizeCombo(comboBox2);

注意!要使其工作,请不要在表单的构造函数中使用 resize 函数。一旦表单已经启动并运行,就可以从 Load 事件或类似事件中使用它。

【讨论】:

效果很好,谢谢 这如何与绑定到数据源的数据表一起工作?在这种情况下,项目是空的。 不,这也适用于 DataTable 作为源。试试看。 抱歉,我无法使用绑定到 DataTable 的 Winforms 组合框来完成这项工作。只是开始 if 结果为零。然后将 DropDownWidth 设置为零会引发异常,如此处所述docs.microsoft.com/en-us/dotnet/api/… 所以我真的很想知道你是如何让它工作的 添加了我用来回答的 DataTable 测试代码。但是,是的,将宽度设置为 0 是一个愚蠢的想法。应该将其重置为组合框的宽度。

以上是关于ComboBox 自动 DropDownWidth 与 DataSource 类型无关的主要内容,如果未能解决你的问题,请参考以下文章

winform combobox自动选择问题。

AutoCompleteTextView

EasyUI combobox的panelHeight自动高度

DataSource 更改时,ComboBox 不会自动更新?

c# 实现ComboBox自动模糊匹配

有界ComboBox自动完成排序