I have a WinForms application with ComboBox in it. I want to programatically select an item depending on its value.
I tried using IndexOf but it requires the whole object, I want to do it only by value. Items are ObjectCollection and I can't use Linq on it (or don't know how).
In one place I'm setting its source like that:
private void SetItems()
{
var items = new List<ComboItem>(3);
//Add items to the list
combo.BeginUpdate();
combo.DataSource = items;
combo.ValueMember = "Value";
combo.DisplayMember = "Name";
combo.EndUpdate();
}
private class ComboItem
{
public int Value { get; set; }
public string Name { get; set; }
}
Then (in other place) I want to set selected item depending on the value. E. g. if I had the combo values:
"Option1": 2,
"Option2": 5,
"Option3": 10
I would like to do something like:
combo.Items.SelectedValue = 5
And have in combo selected Option2. Is it even possible?
1) When setting up DataSource and ValueMember for a ComboBox, to select specific value, use SelectedValue property.
Example - Assign SelectedValue
comboBox1.SelectedValue = 5;
2) When all the item of ComboBox are of type of T, you can searching between items using ComboBox.Items.Cast<T>() assign it to SelectedItem.
Example - Search using ComboBox.Items
Since all items of your ComboBox are of type of T, you can use linq Cast<T> to cast ObjectCollection to IEnumerable<T>. For example:
comboBox1.SelectedItem = comboBox1.Items.Cast<ComboItem>()
.Where(x => x.Value == 5).FirstOrDefault();
Remember to add using System.Linq;.
Related
I have one combobox in which I have set DataSource Value, but when I try to set SelectedValue, the ComboBox returns null. so please help.
BindingList<KeyValuePair<string, int>> m_items =
new BindingList<KeyValuePair<string, int>>();
for (int i = 2; i <= 12; i++)
m_items.Add(new KeyValuePair<string, int>(i.ToString(), i));
ComboBox cboGridSize = new ComboBox();
cboGridSize.DisplayMember = "Key";
cboGridSize.ValueMember = "Value";
cboGridSize.DataSource = m_items;
cboGridSize.SelectedValue = 4;
when I set SelectedValue with 4 then it returns NULL.
Agree with #Laazo change to string.
cboGridSize.SelectedValue = "4";
or somthing similar to this
int selectedIndex = comboBox1.SelectedIndex;
Object selectedItem = comboBox1.SelectedItem;
MessageBox.Show("Selected Item Text: " + selectedItem.ToString() + "\n" +
"Index: " + selectedIndex.ToString());
and refer to this looks as if it would be good for your issue:
https://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.selecteditem(v=vs.110).aspx
How do I set the selected item in a comboBox to match my string using C#?
Getting selected value of a combobox
I came across this question while also trying to solve this problem. I solved it by creating the following extension method.
public static void ChooseItem<T>(this ComboBox cb, int id) where T : IDatabaseTableClass
{
// In order for this to work, the item you are searching for must implement IDatabaseTableClass so that this method knows for sure
// that there will be an ID for the comparison.
/* Enumerating over the combo box items is the only way to set the selected item.
* We loop over the items until we find the item that matches. If we find a match,
* we use the matched item's index to select the same item from the combo box.*/
foreach (T item in cb.Items)
{
if (item.ID == id)
{
cb.SelectedIndex = cb.Items.IndexOf(item);
}
}
}
I also created an interface called IDatabaseTableClass (probably not the best name). This interface has one property, int ID { get; set; } To ensure that we actually have an ID to compare to the int id from the parameter.
I'm populating a ListBox in a WinForms application, this way:
listBoxUsers.DataSource = ctx.Users.ToList();
listBoxUsers.DisplayMember = "Name";
listBoxUsers.ValueMember = "Id";
how to retrieve the selected Ids when I'm setting the SelectionMode to MultiSimple
I want to do a foreach loop on them, like this:
foreach(var itemId in listBoxUsers.SelectedValues)//unfortunately not exist
{
int id = int.Parse(itemId);
// . . .
}
Since you know the type of items, you can use such code:
var selectedValues = listBox1.SelectedItems.Cast<User>().Select(x=>x.Id).ToList();
Side Note: The ListBox control lacks a GetItemValue method. A method which should work like GetItemText, but for getting values. In the linked post I shared an extension method to get the value from an item. Using that extension method you can get selected values independent from type of items:
var selectedValues = listBox1.SelectedItems.Cast<object>()
.Select(x => listBox1.GetItemValue(x)).ToList();
If for some reason you are interested to have a text representation for selected values:
var txt = string.Join(",", selectedValues);
Have you tried with the SelectedItems property?
foreach (var item in listBoxUsers.SelectedItems)
{
}
try this:
foreach (DataRowView item in listBoxUsers.SelectedItems)
{
int id=int.parse(item[0].ToString());
}
In my WPF app, i have a Window(all code) that contains DataGrid. There's my DataGrid binding:
using (var db = new CompanyEntities())
{
var stocks = db.Stock;
var query = from s in stocks
select new { s.Id_Product, s.Quantity };
dataGrid.ItemsSource = query.ToList();
}
I want to read cell that is selected in DataGrid. I tried to read it using DataGrid.SelectedItem, but to get to the item i have to cast it to some type. I can't use Stock class, because my DataGrid cells contains 2 out of 3 fields of Stock. So i made another class to represent DataGrid cell:
class TableItem
{
public int Id_Product;
public int? Quantity;
}
And tried to cast it like this:
TableItem x = (TableItem)dataGrid.SelectedItem;
But i get InvalidCastException from type:
'<>f__AnonymousType02[System.Int32,System.Nullable1[System.Int32]]'
to my TableItem type.
So how should i get selected cell of my dataGrid?
My walkaround:
In my CompanyEntites constructor i set:
this.Configuration.ProxyCreationEnabled = false;
And now i can cast Stock s = (Stock)dataGrid.SelectedItem;without an exception, before switching ProxyCreation off, my SelectedItem was DynamicProxy.Stock~~ type.
Change your query like so:
var query = from s in stocks
select new TableItem { Id_Product = s.Id_Product, Quantity = s.Quantity };
And then cast SelectedItem to TableItem, now that it actually IS one. In C#, just because it looks like another class, doesn't mean it is that other class.
Alternatively, don't write a new class just because you happen not to need one property of the existing class. Just use the existing class:
// Don't think you need to call ToList() here
dataGrid.ItemsSource = db.Stock;
...and cast SelectedItem to whatever that is.
my DataGrid cells contains 2 out of 3 fields of Stock:
So what? Is the problem that you get an extra column? Define the columns explicitly, just the ones you need.
currently I have a combobox with three hard coded items.
Each item carries 2 values. I'm using a switch case statement to get the values for each item depending on which item is selected.
Switch(combobox.selectedindex)
{
case 0: // Item 1 in combobox
a = 100;
b = 0.1;
break;
case 1: // Item 2 in combobox
a = 300;
b = 0.5;
break;
//and so on....
}
I'm trying to add a feature to allow the user to add more items into the combobox with inputted a and b values. How would i be able to dynamically add case statements and define the values under each case condition? I've had a look at using a datatable instead but I don't know how to get multiple valuemembers out of the datatable when one item is selected.
Also, I would like to save the user added items and it's corresponding values to a .dat file. So when the program is re-opened it will be able to load the list of items added by the user from the file. I considered using streamwriter and readline for this but I'm unsure how it would be done.
You can use Binding on a combobox using the DataSource. The ComboBox can also be bound to other things than Primitive values (string/int/hardcoded values). So you could make a small class that represents the values you are setting in your switch statement, and then use the DisplayMember to say which property should be visible in the combobox.
An example of such a basic class could be
public class DataStructure
{
public double A { get; set; }
public int B { get; set; }
public string Title { get; set; }
}
Since you are talking about users adding values to the combobox dynamically, you could use a BindingList that contains the separate classes, this BindingList could be a protected field inside your class, to which you add the new DataStructure when the user adds one, and then automatically updates the combobox with the new value you added.
The setup of the ComboBox, can be done in either Form_Load, or in the Form Constructor (after the InitializeComponent() call), like such:
// your form
public partial class Form1 : Form
{
// the property contains all the items that will be shown in the combobox
protected IList<DataStructure> dataItems = new BindingList<DataStructure>();
// a way to keep the selected reference that you do not always have to ask the combobox, gets updated on selection changed events
protected DataStructure selectedDataStructure = null;
public Form1()
{
InitializeComponent();
// create your default values here
dataItems.Add(new DataStructure { A = 0.5, B = 100, Title = "Some value" });
dataItems.Add(new DataStructure { A = 0.75, B = 100, Title = "More value" });
dataItems.Add(new DataStructure { A = 0.95, B = 100, Title = "Even more value" });
// assign the dataitems to the combobox datasource
comboBox1.DataSource = dataItems;
// Say what the combobox should show in the dropdown
comboBox1.DisplayMember = "Title";
// set it to list only, no typing
comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
// register to the event that triggers each time the selection changes
comboBox1.SelectedIndexChanged += comboBox1_SelectedIndexChanged;
}
// a method to add items to the dataItems (and automatically to the ComboBox thanks to the BindingContext)
private void Add(double a, int b, string title)
{
dataItems.Add(new DataStructure { A = a, B = b, Title = title });
}
// when the value changes, update the selectedDataStructure field
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox combo = sender as ComboBox;
if (combo == null)
{
return;
}
selectedDataStructure = combo.SelectedItem as DataStructure;
if (selectedDataStructure == null)
{
MessageBox.Show("You didn't select anything at the moment");
}
else
{
MessageBox.Show(string.Format("You currently selected {0} with A = {1:n2}, B = {2}", selectedDataStructure.Title, selectedDataStructure.A, selectedDataStructure.B));
}
}
// to add items on button click
private void AddComboBoxItemButton_Click(object sender, EventArgs e)
{
string title = textBox1.Text;
if (string.IsNullOrWhiteSpace(title))
{
MessageBox.Show("A title is required!");
return;
}
Random random = new Random();
double a = random.NextDouble();
int b = random.Next();
Add(a, b, title);
textBox1.Text = string.Empty;
}
}
Like this, you have the selected item always at hand, you can request the values from the properties of the selected, and you don't have to worry about syncing the ComboBox with the items currently visible
From the documentation:
Although the ComboBox is typically used to display text items, you can add any object to the ComboBox. Typically, the representation of an object in the ComboBox is the string returned by that object's ToString method. If you want to have a member of the object displayed instead, choose the member that will be displayed by setting the DisplayMember property to the name of the appropriate member. You can also choose a member of the object that will represent the value returned by the object by setting the ValueMember property. For more information, see ListControl.
So you can just add objects that hold all the information, directly to the Items collection of the ComboBox. Later, retrieve the SelectedItem property and cast it back to the correct type.
I need to display values like "Surreptitiously" and "Discreetly" in a comboBox but thereafter be able to set the comboboxes' SelectedItem based on the underlying DB values for those words (e.g., "S" and "D").
I reckon I can use the comboBoxes' DisplayMember and ValueMember properties for this somehow, but can I subsequently do something analagous to the following with the actual (valuemember) values:
comboBoxAdverbs.SelectedIndex = comboBoxAdverbs.Items.IndexOf(weirdAdverbs[CURRENT_ADVERB]);
As "weirdAdverbs[CURRENT_ADVERB]" contains the values like "S" and "D" it, of course, doesn't find and set the SelectedIndex when the comboBox contains the values "Surreptitiously" and "Discreetly"
If I set the combobox Item Tag value to "S" and "D" (assuming that's possible), I can loop through those values, but I'm hoping there's a one-line way of doing it similar to the "IndexOf()" above.
I use a template class for this and it comes in pretty darn handy. The combo box will show whatever text you want and you can store a value with it.
public class cboItem<T>
{
public cboItem(string name, T value)
{
this.Name = name;
this.Value = value;
}
public string Name { get; set; }
public T Value { get; set; }
public override string ToString()
{
return Name == null ? "" : Name;
}
}
Combo box items can be anything, including classes/structs. By default it will use the ToString() implementation to display items, but if you populate a set of objects you can use DisplayMember and ValueMember to great effect.
As a simple example to give you some ideas we'll bind the combo box to a set of KeyValuePair instances for your weird verb codes and their descriptive names. Alternatively you can use linq to compose anonymous types, or create your own suitable classes/structs.
private void populateCombo()
{
comboBoxAdverbs.Items.Clear();
comboBoxAdverbs.Items.Add( new Tuple<string, string>( "S", "Surreptitiously" ) );
comboBoxAdverbs.Items.Add( new Tuple<string, string>( "D", "Discreetly" ) );
comboBoxAdverbs.DisplayMember = "Item2";
}
Then in your code where you want to select an item matching a provided code: (I.e. "D")
var item = comboBoxAdverbs.Items
.OfType<Tuple<string,string>>()
.FirstOrDefault(i => string.Compare(i.Item1, textBox1.Text, true) == 0);
if (item != null)
comboBoxAdverbs.SelectedItem = item;
This attempts to find the matching item by comparing the key against whatever input (in this case a textbox value) and if it finds a match, sets the SelectedItem to tell the combo box to select it.
** Edit: Whups, had originally use KeyValuePair which I didn't realize was a struct so no Null check-ability. Changed to Tuple (Essentially Pair)
What I found that works for me is to store the selectedindex value, after it's set, into the combobox's Tag property. Then, if the user attempts to change the selectedIndex when it is supposed to be in a "readonly" state, simply change it back to the selectedIndex value stored in the Tag property:
comboBoxPlatypusId.SelectedIndex = comboBoxPlatypusId.Items.IndexOf(DuckbillVals[Duckbill_PlatypusID]);
comboBoxPlatypusId.Tag = comboBoxPlatypusId.SelectedIndex;
...
private void comboBoxFunnyMammals_SelectedValueChanged(object sender, EventArgs e) {
var cb = sender as ComboBox;
if (cb != null)
{
int validSelection = Convert.ToInt32(cb.Tag);
if (cb.SelectedIndex != validSelection) {
cb.SelectedIndex = validSelection;
}
}
}