【问题标题】:DataGridView / ComboBox need two display states (long and short) for informationDataGridView / ComboBox 需要两种显示状态(长和短)来获取信息
【发布时间】:2013-03-27 02:16:45
【问题描述】:

我有一个在水平空间上非常紧凑的 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'”),但这似乎不对。

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

【问题讨论】:

  • 你不能返回一个你想要的固定SubString(0,MaxLength)。在您进行查询时在您的代码中..? MaxLength 将被替换为 Substring(0,25) 例如

标签: c# winforms user-interface datagridview


【解决方案1】:

您需要在 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;

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

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;
    }
}

最终结果如下所示:

【讨论】:

    【解决方案2】:

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

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

    这些是主要变化:

    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

    【讨论】:

    • 试试这个:这几乎是我想要的。由于我在下拉模式下使用组合框(没有编辑,只是选择),很遗憾,在我做出选择后,框仍然显示长描述而不是短描述。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2016-09-03
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 2013-05-19
      • 2014-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多