How to insert 'Empty' field in ComboBox bound to DataTable

后端 未结 13 1321
谎友^
谎友^ 2020-12-14 09:07

I have a combo box on a WinForms app in which an item may be selected, but it is not mandatory. I therefore need an \'Empty\' first item to indicate that no value has been s

相关标签:
13条回答
  • 2020-12-14 09:25

    this.recieptDateTimePicker.SelectedIndex = -1; this.dateCompoBox.SelectedIndex = -1;

    0 讨论(0)
  • 2020-12-14 09:27

    I wrote this method based on the suggestions here by Jason Jackson:

    private IEnumerable<KeyValuePair<object,object>> GetDisplayTable(DataTable dataTable,  DataColumn ValueMember, string sep,params DataColumn[] DisplayMembers)
    {
        yield return new KeyValuePair<object,object>("<ALL>",null);
    
        if (DisplayMembers.Length < 1)
            throw new ArgumentException("At least 1 DisplayMember column is required");
    
        foreach (DataRow r in dataTable.Rows)
        {
            StringBuilder sbDisplayMember = new StringBuilder();
            foreach(DataColumn col in DisplayMembers)
            {
                if (sbDisplayMember.Length > 0) sbDisplayMember.Append(sep);
                sbDisplayMember.Append(r[col]);
            }
            yield return new KeyValuePair<object, object>(sbDisplayMember.ToString(), r[ValueMember]);
        }
    }
    

    Usage:

    bindingSource1.DataSource = GetDisplayTable(
                /*DataTable*/typedDataTable, 
                /*ValueMember*/typedDataTable.IDColumn, 
                /*DisplayColumn Seperator*/" - ",
                /*List of Display Columns*/
                typedDataTable.DB_CODEColumn,
                typedDataTable.DB_NAMEColumn);
    
    comboBox1.DataSource = bindingSource1;
    comboBox1.DisplayMember = "Key";
    comboBox1.ValueMember = "Value";
    
    //another example without multiple display data columns:
    bindingSource2.DataSource = GetDisplayTable(
                /*DataTable*/typedDataTable, 
                /*ValueMember*/typedDataTable.IDColumn, 
                /*DisplayColumn Seperator*/null,
                /*List of Display Columns*/
                    typedDataTable.DESCColumn );
    

    further down, where the Selected Value is consumed:

    if (comboBox1.SelectedValue != null)
         // Do Something with SelectedValue   
    else 
         // All was selected (all is my 'empty')
    

    This will allow to display several columns concatenated in the ComboBox, while keeping the Value member to the single identifier + it uses the iterator block with the BindingSource, BindingSource might be overkill for your situation.

    Сomments and suggestions are welcome.

    0 讨论(0)
  • 2020-12-14 09:28

    I had a similar challenge. As part of the form load event I set the SelectedIndex of the control to -1

    ie

    private void Form1_Load(object sender, EventArgs e)
    {         
        this.TableAdapter.Fill(this.dsListOfCampaigns.EvolveCampaignTargetListMasterInfo);
        this.comboCampaignID.SelectedIndex = -1;
    }
    

    Effectively, the combo box is populated and the first item is selected. Then the item is unselected. May not be a viable solution for all cases.

    0 讨论(0)
  • 2020-12-14 09:29

    I usually create an iterator for this type of thing. It avoids polluting your data, and works well with data-binding:

    DataTable hierarchies = _database.GetAvailableHierarchies(cmbDataDefinition.SelectedValue.ToString()).Copy();//Calls SP
    cmbHierarchies.DataSource = GetDisplayTable(hierarchies);
    cmbHierarchies.ValueMember = "guid";
    cmbHierarchies.DisplayMember = "ObjectLogicalName";
    
    ...
    
    private IEnumerable GetDisplayTable(DataTable tbl)
    {
        yield return new { ObjectLogicalName = string.Empty, guid = Guid.Empty };
    
        foreach (DataRow row in tbl.Rows)
            yield return new { ObjectLogicalName = row["ObjectLogicalName"].ToString(), guid = (Guid)row["guid"] };
    }
    

    Disclaimer: I have not compiled this code, but have used this pattern many times.

    Note: I have been in WPF and ASP.Net land for the last couple of years. Apparently the Winforms combo box wants an IList, not an IEnumerable. A more costly operation would be to create a list. This code is really stream-of-conciseness and I really, really have not compiled it:

    DataTable hierarchies = _database.GetAvailableHierarchies(cmbDataDefinition.SelectedValue.ToString()).Copy();
    List<KeyValuePair<string, Guid>> list = new List<KeyValuePair<string, Guid>>(hierarchies.Rows.Cast<DataRow>().Select(row => new KeyValuePair<string, Guid>(row["Name"].ToString(), (Guid)row["Guid"])));
    list.Insert(0, new KeyValuePair<string,Guid>(string.Empty, Guid.Empty));
    cmbHierarchies.DataSource = list;
    cmbHierarchies.ValueMember = "Value";
    cmbHierarchies.DisplayMember = "Key";
    
    0 讨论(0)
  • 2020-12-14 09:30

    Instead of adding a new row to your datatable, just bind the data to the combobox and at load set the SelectedIndex to -1. This will cause the selection to be null until the user selects an item.

    I clipped this from one of my current projects.

            Attorney_List_CB.DataSource = DA_Attorney_List.BS.DataSource;
            Attorney_List_CB.DisplayMember = "Attorney Name";
            Attorney_List_CB.SelectedIndex = -1;      
    

    In order to clear the selection I usually insert a button that sets the SelectedIndex back to -1.

        private void Clear_Selection_BTN_Click(object sender, EventArgs e)
        {
            Attorney_List_CB.SelectedIndex = -1;  // Clears user selection
        }
    

    Finally, once I validate the data on my form, if the SelectedIndex of any combobox is -1 then it is skipped, or I will generate some type of default value such as "N/A" or whatever I need under the circumstances.

    0 讨论(0)
  • 2020-12-14 09:33

    I have found this way:

        DataTable hierarchies = new DataTable(); 
    
        cmbHierarchies.BeginUpdate();
        cmbHierarchies.ValueMember = this.Value;
        cmbHierarchies.DisplayMember = this.Display;
        hierarchies = DataView.ToTable();
        cmbHierarchies.DataSource = table;
        cmbHierarchies.EndUpdate();
    
        //Add empty row
        DataRow row = table.NewRow();
        table.Rows.InsertAt(row, 0);
        cmbHierarchies.SelectedIndex = 0;
    
    0 讨论(0)
提交回复
热议问题