3

我有一个在水平空间上非常紧凑的 DataGidView,还有一个描述相当冗长的列。

我想做的是创建一个 ComboBox 列:

  1. 显示描述的缩短版本
  2. 在下拉列表中有完整的描述
  3. 幕后处理实际价值

例如,我在下面有这个人为的例子。真正的列表可以有 20-30 个项目,其中的文本很长:

Code    Short      DropDown Text
 1      BigBox     Boxes larger than 6' x 6'
 2      SmBox      Boxes smaller than 6' x 6'
 3      BigBrl     Barrel 55 gallons
 4      SmBrl      Barrel less than 55 gallons

所以我想展示的是:

在此处输入图像描述

当我打开下拉列表时,我想看到:

在此处输入图像描述

当然,当我查询单元格的值时,我想要“1”。

我可以分叉并将“短”描述作为较长描述的第一部分(“BigBx Boxes 大于 6' x 6'”),但这似乎不正确。

我正在寻找有关实现此目标的最佳方法的建议。还没有代码显示,因为我不太确定从哪里开始。

4

3 回答 3

2

您需要更改 DropDown 和 DropDownClosed 事件组合框的 DisplayMember。

在事件下拉菜单中,您需要将 DisplayMember 更改为您的长名称。我发现的一件事是更改 DisplayMember 会重置 SelectedIndex,因此您需要保存它,然后在更改显示后将其重置。

int i = comboBox1.SelectedIndex;
comboBox1.DisplayMember = "LongNm";
comboBox1.SelectedIndex = i;

您需要使用 DropDownClosed 事件和短名称重复此过程以返回到您的关闭显示。

int i = comboBox1.SelectedIndex;
comboBox1.DisplayMember = "ShortNm";
comboBox1.SelectedIndex = i;

我遇到的最后一个问题是更改组合框下拉菜单的宽度。我在这里找到了执行此操作的代码。我的最终代码如下所示:

public partial class Form1 : Form
{
    List<ComboData> data;
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        data = new List<ComboData>();
        data.Add(new ComboData(1, "BigBox", "Boxes larger than 6x6"));
        data.Add(new ComboData(2, "SmBox", "Boxes small than 6x6"));
        data.Add(new ComboData(3, "BirBrl", "Barrel 55 Gallons"));
        data.Add(new ComboData(4, "smBrl", "Barrel less than 55 gallons"));

        comboBox1.DataSource = data;
        comboBox1.DisplayMember = "ShortNm";
    }

    private void comboBox1_DropDown(object sender, EventArgs e)
    {
        int i = comboBox1.SelectedIndex;
        comboBox1.DisplayMember = "LongNm";
        comboBox1.SelectedIndex = i;


        ComboBox senderComboBox = (ComboBox)sender;
        int width = senderComboBox.DropDownWidth;
        Graphics g = senderComboBox.CreateGraphics();
        Font font = senderComboBox.Font;
        int vertScrollBarWidth =
            (senderComboBox.Items.Count > senderComboBox.MaxDropDownItems)
            ? SystemInformation.VerticalScrollBarWidth : 0;

        int newWidth;
        foreach (ComboData s in ((ComboBox)sender).Items)
        {
            newWidth = (int)g.MeasureString(s.LongNm, font).Width
                + vertScrollBarWidth;
            if (width < newWidth)
            {
                width = newWidth;
            }
        }
        senderComboBox.DropDownWidth = width;
    }

    private void comboBox1_DropDownClosed(object sender, EventArgs e)
    {
        int i = comboBox1.SelectedIndex;
        comboBox1.DisplayMember = "ShortNm";
        comboBox1.SelectedIndex = i;
    }
}

public class ComboData
{
    public int Code;
    public string ShortNm
    {
        get;
        set;
    }
    public string LongNm
    {
        get;
        set;
    }

    public ComboData(int c, string s, string l)
    {
        Code = c;
        ShortNm = s;
        LongNm = l;
    }
}

最终结果如下所示:

封闭的组合框 打开组合框

于 2013-04-17T14:59:51.520 回答
1

我想我几乎拥有你想要的东西。一个小的折衷方案:在您编辑值时,组合框会显示截断的 long 值。否则这应该很适合你。

我的源代码是这个例子的一个稍微编辑过的版本。在示例中,它们有一个可通过组合框列编辑的枚举。我的扩展现在将组合框更改为具有显示和值成员(显示成员是长文本,值成员是实际的枚举值),并且在正常显示单元格时,单元格格式化事件开始发挥作用,覆盖显示

这些是主要变化:

private static T GetAttribute<T>(Enum value)
{
    T attribute = value.GetType()
        .GetMember(value.ToString())[0].GetCustomAttributes(typeof(T), false)
        .Cast<T>()
        .SingleOrDefault();
    return attribute;
}

DataGridViewComboBoxColumn CreateComboBoxWithEnums()
{
    DataGridViewComboBoxColumn combo = new DataGridViewComboBoxColumn();
    //combo.DataSource = Enum.GetValues(typeof(Title));        

    var datatable = new DataTable(); //Setup a DataTable for your ComboBox Column
    datatable.Columns.Add("col1", typeof(string));
    datatable.Columns.Add("col2", typeof(Title));

    foreach (Title item in Enum.GetValues(typeof(Title)))
        datatable.Rows.Add(GetAttribute<DescriptionAttribute>(item).Description, item);

    combo.DisplayMember = "col1";
    combo.ValueMember = "col2";
    combo.DataSource = datatable;
    combo.DropDownWidth = 200;
    combo.DataPropertyName = "Title";
    combo.Name = "Title";
    return combo;
}

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (e.ColumnIndex == 0)//where Column1 is your combobox column
    {
        var val = dataGridView1[e.ColumnIndex, e.RowIndex].Value;
        if (val != null)
        {
            e.Value = ((Title)val).ToString();
            e.FormattingApplied = true;
        }
    }
}

public enum Title
{
    [Description("This better be thy king!")]
    King,

    [Description("aka wanna-be-king")]
    Sir
};

完整代码: http: //pastebin.com/Mp9DRvDn

于 2013-04-04T21:41:03.953 回答
0

您可以使用单击事件或下拉事件来检测用户何时尝试打开组合框。然后在组合框正下方显示一个带有较长字符串的列表框。当用户从列表框中选择一个字符串时,在组合框中设置相应的值。

于 2013-04-04T21:35:56.523 回答