How to set selectedValue to Controls.Combobox in c#? - c#

I have a combobox and I see that I am not able to set SelectedValue like this:
cmbA.SelectedValue = "asd"
So I tried to do this
cmbA.SelectedIndex = cmbA.FindString("asd");
Based on How to set selected value from Combobox?
I realised that my combobox is a System.Windows.Controls.ComboBox and not a System.Windows.Forms.ComboBox.
That means that FindString() is not available.
Based on User Control vs. Windows Form I get that forms are the container for controls, but I dont get why the Controls.ComboBox does not implement FindString().
Do I have to write my own code to do what FindString() does for Forms.ComboBox?

WPF ComboBoxes are not the same as WinForms ones. They can display a collection of objects, instead of just strings.
Lets say for example if I had
myComboBox.ItemsSource = new List<string> { "One", "Two", "Three" };
I could just use the following line of code to set the SelectedItem
myComboBox.SelectedItem = "Two";
We're not limited to just strings here. I could also say I want to bind my ComboBox to a List<MyCustomClass>, and I want to set the ComboBox.SelectedItem to a MyCustomClass object.
For example,
List<MyCustomClass> data = new List<MyCustomClass>
{
new MyCustomClass() { Id = 1, Name = "One" },
new MyCustomClass() { Id = 2, Name = "Two" },
new MyCustomClass() { Id = 3, Name = "Three" }
};
myComboBox.ItemsSource = data;
myComboBox.SelectedItem = data[0];
I could also tell WPF I want to consider the Id property on MyCustomClass to be the identifying property, and I want to set MyCombbox.SelectedValue = 2, and it will know to find the MyCustomClass object with the .Id property of 2, and set it as selected.
myComboBox.SelectedValuePath = "Id";
myComboBox.SelectedValue = 2;
I could even set the Display Text to use a different property using
myComboBox.DisplayMemberPath = "Name";
To summarize, WPF ComboBoxes work with more than just Strings, and because of the expanded capabilities, FindString is not needed. What you are most likely looking for is to set the SelectedItem to one of the objects that exist in your ItemsSource collection.
And if you're not using ItemsSource, then a standard for-each loop should work too
foreach(ComboBoxItem item in myComboBox.Items)
{
if (item.Content == valueToFind)
myComboBox.SelectedItem = item;
}

I don't know what you are trying to do but I think it would be easier to just do
cmbA.Text = "String";
That way you get your selected item
Else I found an intersting article that could help you out:
Difference between SelectedItem, SelectedValue and SelectedValuePath

Related

Getting the "value" property of a control

I have a method that has a Control parameter. I want to get the value of the control. So if it is a TextBox get the value of the Text property; if it is a NumericUpDown get the value of the Value property and so on.
The problem is that I cannot write something like this:
Method(Control control)
{
control.Text;
}
or
Method(Control control)
{
control.Value;
}
Because there is no guarantee that the control has one of these properties, and what is its name if it does have it.
Is there a way to do something like that?
There isn't such common Value property in Control class.
You should use some if/else or switch/case or a dictionary approach to get the value from the control. Because you know what property you need. The control just provides properties.
For example for a ComboBox, what is the value? Is it SelectedItem, SelectedIndex, SelectedValue, Text? It's usage/opinion based.
The nearest thing to what you are looking for, is relying on DefaultProperty attribute of controls to get the value from that property using relfection. For example, having this method:
public object GetDefaultPropertyValue(Control c)
{
var defaultPropertyAttribute = c.GetType().GetCustomAttributes(true)
.OfType<DefaultPropertyAttribute>().FirstOrDefault();
var defaultProperty = defaultPropertyAttribute.Name;
return c.GetType().GetProperty(defaultProperty).GetValue(c);
}
You can get values this way:
var controls = new List<Control> {
new Button() { Text = "button1" },
new NumericUpDown() { Value = 5 },
new TextBox() { Text = "some text" },
new CheckBox() { Checked = true }
};
var values = controls.Select(x => GetDefaultPropertyValue(x)).ToList();

Setting the start value of an enum ComboBox

been searching for a solution for this problem, found plenty solutions, but nothing changed my code's behaviour. This is in WinForms.
I am loading a form with a ComboBox, that contains the values and names of this enum, that is inside a class named "Node".
class Node
{
public enum NodeType { Yield, Home, Parking, Light, None, Inbound, Outbound }
public NodeType Type;
}
Then in my form, I have a ComboBox named "Type", which is set up like so (from the constructor):
Node node = new Node();
node.Type = Node.NodeType.Home;
Type = new ComboBox();
Type.Location = new Point(77, 41);
Type.Size = new Size(121, 24);
Type.DropDownStyle = ComboBoxStyle.DropDownList;
Type.DisplayMember = "Name";
Type.ValueMember = "Value";
Type.DataSource = Enum.GetValues(typeof(Node.NodeType));
Type.SelectedValue = node.Type;
Controls.Add(Type);
When the program runs, the list shows all the names, and on closing the form I am able to retrieve the selected value via. Type.SelectedValue. My problem is that the ComboBox doesn't start at the value that the Node is already set at. Essentially the line
Type.SelectedValue = node.Type;
doesn't do anything. I've tried using SelectedItem which didn't change anything, and
Type.SelectedIndex = (int)node.Type;
Which caused an ArgumentOutOfRangeException.
So, my question is: how do I set the start value of the ComboBox?
There are several mistakes in that code.
First, enum does not have Name and Value properties (in fact it does not have any property), so DisplayMember and ValueMember cannot be used and should be left blank (default). Which in turn means SelectedValue cannot be used and you need to use SelectedItem instead.
Second, you are using list data bound mode for the list portion of your ComboBox by setting DataSource property instead of populating Items, which is fine, but data binding occurs later in the process, so inside the constructor the Items property is empty and SelectedItem has no effect. In order to fix that, you need to move the data initialization part to your form Load event.
So, in your form constructor you'll have this:
Type = new ComboBox();
Type.Location = new Point(77, 41);
Type.Size = new Size(121, 24);
Type.DropDownStyle = ComboBoxStyle.DropDownList;
Controls.Add(Type);
and in your form Load event - this:
Node node = new Node();
node.Type = Node.NodeType.Home;
Type.DataSource = Enum.GetValues(typeof(Node.NodeType));
Type.SelectedItem = node.Type;
Type.SelectedIndex = index from your enum, for example the enum is {"apple", "pear", "pineapple"}, and you want pear by deafult, so Type.SelectedIndex = 1

Combo Boxes With Multiple Columns

I've read that combo boxes cannot have multiple columns. Which leaves me a bit stuck since what I want to do is display one field from a table, but return the corresponding value from a second field in the same table i.e.
I'd like to show CustomerNames in the combo box, but when the user selects a name, the CustomerID field is returned instead. Whats the best work around for this?
Best way is to use ComboBoxes DisplayMember and ValueMember properties
set the ComboBox.DisplayMember to the property you want to display. Use ValueMember for property you want to return. Then you can use the ComboBox.SelectedValue to get the current/selected ValueMember
You don't need multiple columns to implement it.
class Member
{
public string Name{get;set;}
public string Address{get;set;}
public int ID{get;set;}
public string Description
{
get
{
return string.Format("{0}, {1}", Name, Address);
}
}
}
var members = new []
{
new Member(){ID = 1, Name = "John", Address = "Addr 1"},
new Member(){ID = 2, Name = "Mary", Address = "Addr 2"}
};
m_ComboBox.DataSource = members;
m_ComboBox.DisplayMember = "Description"
m_ComboBox.ValueMember = "ID";
now you can access seleceted ID
var selectedID = m_ComboBox.CelectedValue();
The value of the ComboBoxItem does not have to be the same as the Text, consider using the ID as the value.
You can achieve the desired behaviour by setting the DisplayMember and ValueMember properties of the ComboBox to "CustomerName" and "CustomerID" respectively.
Take a look at the ValueMember property. You should set this to CustomerID. After you bind to your combobox, the actual field displayed to the user will be the CustomerName, but when you want to get the value of 'CustomerName', it will return the CustomerID.
When you want to get the value of the combobox, simply reference the SelectedValue.
If you are adamant about displaying both of these in the combobox, there are some hackish ways of doing this but I would recommend reviewing your requirements again and seeing if it is absolutely necessary.
Alternatively, you can define KeyValuePair objects with your intended Ids and text fields. Feed them to the combo, since its Items property is a collection of objects. Then, for retrieval use a cast like
var x = (KeyValuePair)combo.Items[0];
and then acces then Key and Value properties of x.
You can use Tag property of ComboBoxItem to store the value.

How do you bind a data field value to a combobox index?

This may have been already asked but I can't seem to find this specific question, so here goes...
I have a form in C# where every textbox is bound to a field in a row. Rows can be cycled through by some buttons on the bottom but all the data displayed at a time in the from is from one row. Any changes that are made get updated back to the database when the user clicks "update"
One field (class) is an enumeration (0,1,2) where only the value is stored in the database, but doesn't mean much to the user. I was asked to make this more obvious to the user, so I decided to go with a dropdown style combo box. Since the database didn't have any reference to what the values meant, I decided to use the DataBindings instead of DataSource so I could just use the index as the data bind, but it seems that SelectedItem or Value are not the way to do this.
Here is my goal:
1 exists in database, so "B" is selected in combo box.
User selects "C" and updates the database, 2 is now stored in the database.
Any thoughts on what I need to get this working?
I assume you have a BindingSource on your form to bind to the data. You can bind the SelectedIndex property of the ComboBox as follows:
comboBox.DataBindings.Add("SelectedIndex", bindingSource, "PropertyInTheDataSource");
Actually I was able to bind it to a custom Object. It's a little too much work for such a simple task. But you have complete control on Display/Value pairs. Anyway, I thought I'd share and you decide:
Create a new class (say CustomItem) with 2 fields:
Public int Value{get;set;}
public string Title {get;set;}
Then in you form:
var item1 = new CustomItem() { Title = "A", Value = 10 };
var item2 = new CustomItem() { Title = "B", Value = 20 };
var item3 = new CustomItem() { Title = "C", Value = 30 };
var lst = new List<CustomItem>();
lst.Add(item1);
lst.Add(item2);
lst.Add(item3);
comboBox1.DataSource = lst;
comboBox1.DisplayMember = "Title";
comboBox1.ValueMember = "Value";
Now You have a databound combobox in case you don't have BndingSource in your form.
Just remember to define your class's Title and Value as properties otherwise it wouldn't work.

Binding Listbox to List<object> in WinForms

What's the simplest way to bind a Listbox to a List of objects in Windows Forms?
You're looking for the DataSource property:
List<SomeType> someList = ...;
myListBox.DataSource = someList;
You should also set the DisplayMember property to the name of a property in the object that you want the listbox to display. If you don't, it will call ToString().
Binding a System.Windows.Forms.Listbox Control to a list of objects (here of type dynamic)
List<dynamic> dynList = new List<dynamic>() {
new {Id = 1, Name = "Elevator", Company="Vertical Pop" },
new {Id = 2, Name = "Stairs", Company="Fitness" }
};
listBox.DataSource = dynList;
listBox.DisplayMember = "Name";
listBox.ValueMember = "Id";
Pretending you are displaying a list of customer objects with "customerName" and "customerId" properties:
listBox.DataSource = customerListObject;
listBox.DataTextField = "customerName";
listBox.DataValueField = "customerId";
listBox.DataBind();
Edit: I know this works in asp.net - if you are doing a winforms app, it should be pretty similar (I hope...)
Granted, this isn't going to provide you anything truly meaningful unless the objects have properly overriden ToString() (or you're not really working with a generic list of objects and can bind to specific fields):
List<object> objList = new List<object>();
// Fill the list
someListBox.DataSource = objList;
ListBox1.DataSource = CreateDataSource();
ListBox1.DataTextField = "FieldProperty";
ListBox1.DataValueField = "ValueProperty";
Please refer to this article for detailed examples.
I haven 't seen it here so i post it because for me is the best way in winforms:
List<object> objList = new List<object>();
listBox.DataSource = objList ;
listBox.Refresh();
listBox.Update();
There are two main routes here:
1: listBox1.DataSource = yourList;
Do any manipulation (Add/Delete) to yourList and Rebind.
Set DisplayMember and ValueMember to control what is shown.
2: listBox1.Items.AddRange(yourList.ToArray());
(or use a for-loop to do Items.Add(...))
You can control Display by overloading ToString() of the list objects or by implementing the listBox1.Format event.
For a UWP app:
XAML
<ListBox x:Name="List" DisplayMemberPath="Source" ItemsSource="{x:Bind Results}"/>
C#
public ObservableCollection<Type> Results

Categories