C# DataGridView/ComboBox需要两种显示状态(长和短)来获取信息

C# DataGridView/ComboBox需要两种显示状态(长和短)来获取信息,c#,winforms,user-interface,datagridview,C#,Winforms,User Interface,Datagridview,我有一个DataGidView,它在水平空间上非常紧凑,还有一个专栏有相当长的描述 我想做的是创建一个组合框列: 显示说明的缩短版本 在下拉列表中有完整的描述 幕后处理的是实际价值 举个例子,我在下面有一个人为的例子。真正的列表可以有20-30个项目,其中包含相当长的文本: Code Short DropDown Text 1 BigBox Boxes larger than 6' x 6' 2 SmBox Boxes smaller t

我有一个DataGidView,它在水平空间上非常紧凑,还有一个专栏有相当长的描述

我想做的是创建一个组合框列:

  • 显示说明的缩短版本
  • 在下拉列表中有完整的描述
  • 幕后处理的是实际价值
  • 举个例子,我在下面有一个人为的例子。真正的列表可以有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”

    我可以分门别类,把“短”描述作为较长描述的第一部分(“大于6'x 6'”的BigBx框),但这似乎不对


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

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

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

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

    这些是主要的变化:

    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
    };
    
    private static GetAttribute(枚举值)
    {
    T attribute=value.GetType()
    .GetMember(value.ToString())[0]。GetCustomAttributes(typeof(T),false)
    .Cast()
    .SingleOrDefault();
    返回属性;
    }
    DataGridViewComboBoxColumn CreateComboxWithEnums()
    {
    DataGridViewComboBoxColumn组合=新建DataGridViewComboxColumn();
    //combo.DataSource=Enum.GetValues(typeof(Title));
    var datatable=new datatable();//为组合框列设置一个datatable
    datatable.Columns.Add(“col1”,typeof(string));
    datatable.Columns.Add(“col2”,typeof(Title));
    foreach(Enum.GetValues中的标题项(typeof(Title)))
    datatable.Rows.Add(GetAttribute(item).Description,item);
    combo.DisplayMember=“col1”;
    combo.ValueMember=“col2”;
    combo.DataSource=datatable;
    combo.DropDownWidth=200;
    combo.DataPropertyName=“Title”;
    combo.Name=“Title”;
    返回组合;
    }
    私有void dataGridView1_CellFormatting(对象发送方,DataGridViewCellFormattingEventArgs e)
    {
    if(e.ColumnIndex==0)//其中Column1是您的组合框列
    {
    var val=dataGridView1[e.ColumnIndex,e.RowIndex]。值;
    如果(val!=null)
    {
    e、 Value=((Title)val).ToString();
    e、 FormattingApplied=true;
    }
    }
    }
    公共枚举标题
    {
    [描述(“这最好是你的国王!”)
    国王,
    [描述(“aka想成为国王”)]
    先生
    };
    

    完整代码:

    您需要更改事件下拉列表和下拉关闭列表中组合框的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;
        }
    }
    
    公共部分类表单1:表单
    {
    列出数据;
    公共表格1()
    {
    初始化组件();
    }
    私有void Form1\u加载(对象发送方、事件参数e)
    {
    数据=新列表();
    添加(新的组合数据(1,“大盒子”,“大于6x6的盒子”);
    添加(新的组合数据(2,“SmBox”,“小于6x6的框”);
    数据。添加(新的组合数据(3,“比尔”、“桶55加仑”);
    数据。添加(新组合数据(4,“smBrl”,“桶小于55加仑”);
    comboBox1.DataSource=数据;
    comboBox1.DisplayMember=“ShortNm”;
    }
    private void comboBox1下拉列表(对象发送方,事件参数e)
    {
    int i=组合框1.SelectedIndex;
    comboBox1.DisplayMember=“LongNm”;
    comboBox1.SelectedIndex=i;
    组合框发送者组合框=(组合框)发送者;
    int width=senderComboBox.DropDownWidth;
    Graphics g=senderComboBox.CreateGraphics();
    Font=senderComboBox.Font;
    整数垂直滚动条宽度=
    (senderComboBox.Items.Count>senderComboBox.MaxDropDownItems)
    ?SystemInformation.VerticalScrollBarWidth:0;
    int newWidth;
    foreach((组合框)sender.Items中的组合数据)
    {
    newWidth=(int)g.MeasureString(s.LongNm,font).Width
    +垂直宽度;
    如果(宽度<新宽度)
    {
    宽度=新宽度;
    }
    }
    senderComboBox.DropDownWidth=宽度;
    }
    私有void comboBox1\u DropDownClosed(对象发送方,事件参数e)
    {
    int i=组合框1.SelectedIndex;
    comboBox1.DisplayMember=“ShortNm”;
    comboBox1.SelectedIndex=i;
    }
    }
    公共类组合数据
    {
    公共整数码;
    公共字符串缩写
    {
    得到;
    设置
    }
    公共字符串长度
    {
    得到;
    设置
    }
    公共组合数据(int c、字符串s、字符串l)
    {
    代码=c;
    短nm=s;
    瞧