How to set ComboBox index? - c#

"I understand question title may be repeated but did not find a solution which I am looking for."
A groupbox which contains approx 50 controls in the combination of textboxes and comboBoxes. I have to set value for them and don't want to write 50 individual lines to set value for each control, so I came up with below code. But this is not working in case of comboboxes. OR If you guys can suggest something better that would be great.
if(controlsInGroupBox == editStep.Count)
{
int i = 0;
foreach (Control ctr in universalGroupBoxObject.Controls)
{
if (ctr is TextBox)
{
ctr.Text = editStep[i];
}
if (ctr is ComboBox)
{
//ctr.SelectedIndex = cntrlObjListMain.comboBoxLocation.FindStringExact(editStep[i]);
//ctr.SelectedIndex is not working
}
i++;
}
}

If you databind your data to the combobox then the first item is selected by default saving you having to select one.
E.G.
List<string> items = new List<string>() { "aa", "bb", "cc", "dd" };
combobox1.DataSource = items;
SelectedIndex should work as long as you have items in your list.
ctr.SelectedIndex = ctr.Items.Count > 0 ? 0 : -1;
The above will select an item if there are any items, otherwise won't select anything.

Related

C# WinForms ComboBox: AutoComplete does not sort descending

In a WinForms dataviewer project I've made a ComboBox to select a filter value. The list items come from of a database query. They are sorted descending. The ComboBox uses AutoCompleteMode.Append. Although the dropdown list is sorted descending, the AutoComplete always suggests the lowest matching value instead of the highest. This happens even if I explicitly populate the AutoCompleteCustomSource with descending data.
Does anyone know how to make the AutoComplete suggesting the highest matching value?
The ComboBox looks like this after typing "010":
This is a part of the dropdown list:
...
012-0020-00
010-0070-00
010-0069-00
010-0068-00
008-1018-00
...
Why this matters:
I will use this filter for various string data containing numbers, like parts codes, document codes, project codes etc. Newer entries have higher numbers. And the newest entries are queried most often. In the above example, 010-0070-00 ist the newest part code of the 010 group. Therefore I expect the AutoComplete to show 010-0070-00 after I have typed 010.
This project replaces an MS Access front end. An Access ComboBox suggests the highest value if the list is sorted descending resp. the lowest value if sorted ascending. But Access ComboBoxes are not WinForms controls.
Any suggestions are welcome.
Example using a ToolStripDropDown:
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
String[] data = "012-0020-00,010-0070-00,010-0069-00,010-0068-00,008-1018-00".Split(',');
ComboBox combo = new ComboBox();
//ToolStripDropDownMenu menu = new ToolStripDropDownMenu(); // has image/icon border
ToolStripDropDown menu = new ToolStripDropDown(); // plain menu, no image/icon border
menu.AutoClose = false;
bool isAdjusting = false;
combo.LostFocus += delegate {
if (!isAdjusting)
menu.Close();
};
menu.ItemClicked += (o, e) => {
isAdjusting = true;
combo.Text = e.ClickedItem.Text;
menu.Close();
isAdjusting = false;
};
combo.TextChanged += delegate {
if (isAdjusting)
return;
isAdjusting = true;
String prefix = combo.Text;
menu.SuspendLayout();
for (int i = menu.Items.Count - 1; i >= 0; i--) {
var item = menu.Items[i];
menu.Items.RemoveAt(i);
item.Dispose();
}
foreach (String part in data) {
if (part.StartsWith(prefix))
menu.Items.Add(new ToolStripMenuItem(part));
}
menu.ResumeLayout();
menu.Show(combo, 0, combo.Height);
combo.Focus();
combo.SelectionStart = prefix.Length;
isAdjusting = false;
};
Form f7 = new Form();
f7.Controls.Add(combo);
Application.Run(f7);

C# What does setting the SelectedIndex of a combobox to -1 do?

When I was working on one of my projects I was trying to write to a datasourced combobox and then write a value into the combobox like below:
//Create list for combobox
List<string> companyList= new List<string>() { "", "Company1", "Company2" };
//Datsource list to combobox
cbCompanyName.DataSource = companyList;
//If form is set to import data and the billing address is not null
if (importAddress && StaticValues.billAddress != null)
{
//Fill all fields with data from Static Values class
cbCompanyName.Text = StaticValues.billAddress.CompanyName;
cbCountry.Text = StaticValues.billAddress.Country;
}
else
{
//Set country to US
cbCountry.SelectedIndex = 0;
}
however the line cbCompanyName.Text = StaticValues.billAddress.CompanyName; ran without writing any text to the combobox, until I set the selected index of the combobox to -1. What does setting the combobox selected index to -1 do that would change this as apposed to setting the selected index to 0?
Setting the SelectedIndex on a ComboBox to -1 deselects (SelectedItem is NULL). Setting to 0 selects the first item in Items
Combobox needs to know what is my value and display member,
giving the datasource is not enough for it.
I think you can use like this or
// comboBox.DisplayMember = "Text";
// comboBox.ValueMember = "Value";
int =0;
companyList.forEach(x=> comboBox.Items.Add(new { Text = x.toString(), Value =i++ }));
comboBox1.SelectedIndex = 0;
you can look this article
similar question and answers

How can I iterate through selected ComboBoxes controls with a loop in C#?

I am working in a simple C# form. I have a total of 20 ComboBoxes . 10 ComboBoxes will contain similar data type and will have very similar name (CB1, CB2, CB3, ... CB10). Each ComboBox was loaded with a list of 5 elements A,B,C,D,E (by this I meant that I added those values to each of the 10 "CB" ComboBoxes). My intend is that the user can have the ability to select items (one out of A,B,C,D,E) from either 1 combobox, or 2 comboboxes, . . . ., or all of them (10 comboboxes).
I wish to store the data from the ComboBoxes where an item was selected in a list or array. For that I would like to iterate through the 10 ComboBoxes (the comboboxes which names are CB1, CB2, CB3, ..., CB10), check if the an item was selected in the combobox, and store the value selected in the ComboBox into a list (in the code below the list is called symbols). At the end the length of my symbols list (number of items) will depend on how many ComboBoxes the user selected from. Here is the code I am using:
List<string> symbols = new List<string>();
for (int i = 1; i <= 10; i++)
{
var my_comboBox = this.Controls["CB" + i.ToString()];
if (null != my_comboBox.SelectedItem)
{ symbols.add(my_comboBox.Text); }
}
when I run the code I get the following error.
Object reference not set to an instance of an object.
Could anyone please explain what I am doing wrong? I got the code from another question that was posted and answered, below is the link to that question. Thanks in advance.
How can I iterate all ComboBoxes controls with a loop in C#?
I also tried the other alternative proposed on the answers to the questions cited. But it did not work. It does not go through the foreach loop (no error is shown though). Here is the code for option 2.
List<string> symbols = new List<string>();
var comboBoxes = this.Controls.OfType<ComboBox>().Where(x => x.Name.StartsWith("CB"));
foreach (var cmbBox in comboBoxes)
{
if (null != my_comboBox.SelectedItem)
{ symbols.add(my_comboBox.Text); }
}
Again if anyone can please provide me with ideas to what I am doing wrong that would be very nice. Thanks in advance once more.
The ComboBoxes belong to the form as shown in the picture below. In there the ComboBoxes are called component_CB1, component_CB2, component_CB3, ..., component_CB10 (I changed the name of the ComboBoxes in the question to CB to make it easier to understand).
screenshot of my solution explorer
Thanks to everyone who contributed to find the answer to this problem. Please read the comments to identify the contributors.
The answer is that you can iterate through selected ComboBoxes in C#. However for this to work you need to make sure you know to what container control your ComboBoxes are added.
To know to container control your ComboBoxes are added to, go to View → Other Windows → Document Outline. You can see if those controls are directly children of the form or they are children of another container control.
If the ComboBoxes are added to your form directly, then here there are two alternatives to iterate through the ComboBoxes:
ALTERNATIVE 1: (ComboBoxes added to the form directly)
List<string> symbols = new List<string>();
for (int i = 1; i <= 10; i++)
{ //CB is the begining of the name of the comboboxes CB1, CB2, ... CB10
var my_comboBox = this.Controls["CB" + i.ToString()];
if (null != my_comboBox.SelectedItem)
{ symbols.add(my_comboBox.Text); }
}
ALTERNATIVE 2: (ComboBoxes added to the form directly)
List<string> symbols = new List<string>();
//CB is the begining of the name of the comboboxes CB1, CB2, ... CB10
var comboBoxes = this.Controls.OfType<ComboBox>().Where(x=>x.Name.StartsWith("CB"));
foreach (var cmbBox in comboBoxes)
{
if (null != my_comboBox.SelectedItem)
{ symbols.add(my_comboBox.Text); }
}
If the ComboBoxes are added to a different control container (e.g. a tab in a TabControl as in my initial case), you must specify the control container name rather than "this". Here are two alternatives taking as example the ComboBoxes Cb1, CB2, CB3, ..., CB10 that are added to a tab called tab1.
ALTERNATIVE 1: (ComboBoxes added to a tab of a TabControl)
List<string> symbols = new List<string>();
for (int i = 1; i <= 10; i++)
{//CB is the begining of the name of the comboboxes CB1, CB2, ... CB10
var my_comboBox = tab1.Controls["CB" + i.ToString()];
if (null != my_comboBox.SelectedItem)
{ symbols.add(my_comboBox.Text); }
}
ALTERNATIVE 2: (ComboBoxes added to a tab of a TabControl)
List<string> symbols = new List<string>();
//CB is the begining of the name of the comboboxes CB1, CB2, ... CB10
var comboBoxes = tab1.Controls.OfType<ComboBox>().Where(x
=>x.Name.StartsWith("CB"));
foreach (var cmbBox in comboBoxes)
{
if (null != my_comboBox.SelectedItem)
{ symbols.add(my_comboBox.Text); }
}
Thanks for the help again. I hope this can be useful for others.

Drop Down List binded, auto select an Item/make a specific Item first

i have a drop down list on my page with Countries, here is my code behind where i grab the ddl id, and bind my datasource:
DropDownList ddlSalary = (DropDownList)this.FindControl(MyControls.CountryDDL);
if (ddlSalary != null)
{
ddlSalary.DataSource = MyMethods.LoadCountries();
ddlSalary.DataValueField = "Value";
ddlSalary.DataTextField = "Text";
ddlSalary.DataBind();
}
My Countries ive written in are Alphabetical. But id like the option to move a specific one to the top of the List, or perhaps an Auto-Select. Example 'United Kingdom' is first in the list
What would be the most efficient way to go about doing this ?
I think this logic is better suited to be placed in your service/model provider (MyMethods.LoadCountries(); ).
Something like:
public static List<Country> LoadOrderedCountries(){
var orderedCounteries = MyMethods.LoadCountries();
orderedCounteries .Sort(); // Just to make sure alphabetical order, assuming that Country implements IComparable
var defaultCountry = Country.GetDefault();
orderedCounteries .Remove(defaultCountry);
orderedCounteries .Insert(0, defaultCountry);
return orderedCounteries ;
}
Here is a quick & dirty way to do it with SQL. I prefer to do it at database level
What I am doing is selecting the items you want first in the list
Union ALL with items you want in the list in ascending order by name excluding the ones in my first query
Results are with first Item at top irrespective of 2nd query
select * from ( (select Empcode,Empname from
mySchema.Employees where EmpCode not in (90) ) UNION ALL
select EmpCode,EmpName from mySchema.Employeeswhere
EmpCode=90 order by EmpName) as z
You ca also set the value selected on pageLoad as
ddlYourDropDownList.SelectedValue="90";
After databinding your datasource, you can just sort the ListItems
A better way to do so is to do the sorting in your datasource (you haven't supplied enough information regarding where are you getting the data from)
private void SortDDL(ref DropDownList objDDL)
{
ArrayList textList = new ArrayList();
ArrayList valueList = new ArrayList();
foreach (ListItem li in objDDL.Items)
{
textList.Add(li.Text);
}
textList.Sort();
foreach (object item in textList)
{
string value = objDDL.Items.FindByText(item.ToString()).Value;
valueList.Add(value);
}
objDDL.Items.Clear();
for(int i = 0; i < textList.Count; i++)
{
ListItem objItem = new ListItem(textList[i].ToString(), valueList[i].ToString());
objDDL.Items.Add(objItem);
}
}
I normally do this in the databound event
DropDownList ddlSalary = (DropDownList)this.FindControl(MyControls.CountryDDL);
if (ddlSalary != null)
{
ddlSalary.DataSource = MyMethods.LoadCountries();
ddlSalary.DataValueField = "Value";
ddlSalary.DataTextField = "Text";
ddlSalary.DataBind();
ddlSalary.DataBound += ddlSalary_DataBound;
}
protected void ddlSalary_DataBound(object sender, EventArgs e)
{
ListItem MovingItem = ddlSalary.Items.FindByValue("yourvalue");
ddlSalary.Items.Remove(MovingItem);
ddlSalary.Items.Insert(0, MovingItem);
}
Edit: this method is more suited to adding an a "Other" type option, which is not supplied by your datasource. Amby's solution is better than this.

Select the specific column of ListView and print it in a new messagebox in C#.net

I've just started to use ListView in C#.net.
I got to know how to add items and subitems. Going through the listview I wanted to fetch all the data from a whole column with multiple rows.
I want to know how to do this.
I found this code to list a specific selected data from a row:
ListView.SelectedIndexCollection sel = listView1.SelectedIndices;
if (sel.Count == 1)
{
ListViewItem selItem = listView1.Items[sel[0]];
MessageBox.Show(selItem.SubItems[2].Text);
}
That was helpful but i want to list all the items in a row, may be i want to add all the column items in array?
private string[] GetListViewItemColumns(ListViewItem item) {
var columns = new string[item.SubItems.Count];
for (int column = 0; column < columns.Length; column++) {
columns[column] = item.SubItems[column].Text;
}
return columns;
}
I would recommend some caution against doing this. A ListView is really meant to display information, it is not a great collection class. Getting the data out of it is slow and crummy, it can only store strings. Keep the data in your program in its original form, maybe a List<Foo>. Now it is simple and fast.
foreach (ListViewItem item in listView1.Items) {
// Do something with item
}
you could do this by
foreach(ListViewItem item in listView1.Items)
{
foreach(var subtem in item.SubItems)
{
// Do what ever you want to do with the items.
}
}

Categories

Resources