Right now, to be sure I am getting what I want I am using
actionComboBox.Items[actionComboBox.SelectedIndex].ToString()
to retrieve the string that is stored as an item in my TextBox
Does one of the Selected properties return my above statement? I can never seem to get what I want when I use those.
Like, does actionComboBox.SelectedItem as string return the above value?
EDIT:
I guess the true question here is: What do each Selected Property return such as; SelectedItem, SelectedValue, SelectedText.
I think SelectedText returns the text that is selected if you are able to edit the text in the combo box. I don't think you use this property if you have the DropDownList style selected where the user cannot just type values into the combobox.
SelectedValue only applies if you are bind to a datasource. SelectedValue will return the item in the datasource you've selected, or if you have the DisplayMember field filled in, the value of the property/column that you have specified.
SelectedItem will return the selected item if you have just filled in the list items through the designer.
I get burned on these all the time, cause I always forget. The big question in your example is how are the items being populated into the combo box, that will affect the return values of these properties.
ComboBox.Items is a collection of System.Object's, so it can be anything. By default the ComboBox displays the return value of an object's ToString method. Whatever you add to the ComboBox will be what you will get back, though its returned as a System.Object and you will have to convert it back to its original type to access its members.
comboBox.Items.Add("foo");
The above will add a System.String to the ComboBox.
class Foo
{
public String Bar { get; set; }
}
Foo foo = new Foo();
foo.Bar = "Value";
comboBox.Items.Add(foo);
The above will add a Foo to the ComboBox. So to get your values back.
Object obj = comboBox.Items[comboBox.SelectedIndex];
Foo foo = obj as Foo;
if (foo != null) { // check just in case
}
For strings, there's no need for a conversion, calling ToString is fine. It's better to just use SelectedItem instead.
Foo foo = comboBox.SelectedItem as Foo;
if (foo != null) { // again, check to make sure
}
The power of the ComboBox is that since it stores a collection of System.Object, you can store multiple types of objects, but you are in charge of converting it back to whatever usable type it was to begin with when you need to access it.
Related
Given that I added an item to CheckedListBox this way:
checkedListBox1.Items.Add("ItemA");
And let's say that this is the only item in the control:
string s = checkedListBox1.GetItemText(0);
Now the value of s is "0" when I expect "ItemA". Why can't I get correct value using checkedListBox1.GetItemText(int itemIndex) method?
You should pass the object which is an item of CheckedListBox to GetItemText:
MessageBox.Show(checkedListBox1.GetItemText(checkedListBox1.Items[0]);
Otherwise GetItemText returns ToString of passed object.
Use checkedListBox1.Items[0].ToString(); instead of GetItemText()
I have a stored procedure in which I imported as a function in my entity framework model. I want to assign one of the values of the stored proc to my label.text but it doesn't appear in the intellisense. I must be doing something wrong. Can someone please assist?
private void GetBackgroundData()
{
List<GetBackground_Result> results = context.GetBackground().ToList();
lblFullName.Text = results.FullName // FullName doesn't appear in my intellisense
}
results is a List, not a single instance of GetBackground_Result. You need to take a single element from the collection to set the text:
// if there could be multiple elements in the list
lblFullName.Text = results.First().FullName;
// or, if there should only be one element in the list
lblFullName.Text = results.Single().FullName;
Hi may i know how to get the enum value below to bind into the combobox?
I wrote the below code which works well but wonder is this the best way.
public enum CourseStudentStatus
{
Active = 1,
Completed = 2,
TempStopped = 3,
Stopped = 4,
}
//Bind Course Status
Dictionary<string, int> list = new Dictionary<string, int>();
foreach (int enumValue in Enum.GetValues(typeof(CourseStudentStatus)))
list.Add(Enum.GetName(typeof(CourseStudentStatus), enumValue), enumValue);
var column = ((DataGridViewComboBoxColumn)dgv.Columns["studentCourseStatus"]);
column.DataPropertyName = "StudentStatus";
column.DisplayMember = "Key";
column.ValueMember = "Value";
column.DataSource= list.ToList();
----------------- UPDATE -------------------
Hi i have changed my code to this according to Sanjeevakumar Hiremat and it works perfectly.
cbStatus.DataSource = Enum.GetValues(typeof(CourseStudentStatus));
However, when i want to a Get() and want to bind the value back to the cbStatus, it cast error {"Object reference not set to an instance of an object."}
cbStatus.SelectedValue = Course.Status;.
The cbStatus.Datasource is not empty and it has value after bound to cbStatus.DataSource = Enum.GetValues(typeof(CourseStudentStatus));
please advice.
Following should be the simplest way to bind it.
column.DataSource = Enum.GetValues(typeof(CourseStudentStatus));
To get the selected value you need to cast it to the enum type.
CourseStudentStatus selectedValue = (CourseStudentStatus)column.SelectedValue
Enum.GetValues returns an array of the enumType values which can then be bound to any control.
I've tested this on a standalone combobox, not in a combobox column in DataGridView, YMMV.
I don't think there is a best way. I used to do something similar with a GenericListItem<T> class where T is the backing value, in your case, an enum.
This class exposed Display string and Value T properties to bind to. I think I was also overriding ToString because it is the default if you don't specify the DisplayMember. I went further and made a constructor taking just Value and defaulting Display to Value.ToString, which in the case of enums works I think.
I'd then make a List<GenericListItem<T>>, feed that into the DataSource of the column and set the DisplayMember and ValueMember properties accordingly in code. This list is the alternative to the dictionary used in your example.
But I'm not saying it's a better solution :-) however it means you can remove code, say enum iteration, into this class or specialise the class for handling certain data types better, all with the end goal of being inserted into a list and bound to a control.
I am filling items to my ComboBox from a XML file using a DataTable. Currently I have it set so that one column is ComboBox's displaymember and another is it's value member. However this may not always work for me, since I have to set the selectedItem parameter, and value member may not be unique.
I don't know if there is a duplicate of the value member in the table or not, so my idea was that I would put entire DataRow as the value member of the ComboBox and then use ComboBox.SelectedITem = (DataRow)some_data_row; for selecting, and it would always select the right ComboBox object.
How would I accomplish this? IS there a better way of doing this? I'm open to suggestions, however it is very important that I can get to both, display member and value member.
Thank you for your help!
EDIT: Maybe I wasn't clear enough before, however while I am asking if this is the best approach here, I am also asking how to do this. If I don't set the valuemember parameter, the SelectedItem is of DataRowView type... Please note, that I want to use the selectedValue parameter to select items from ComboBox, and if I try to do that without explicitly setting the value member an exception is thrown.
If you bind a ListBox to a DataTable, you're actually binding it to a DataView that represents that DataTable (DataTable implements IListSource, and that returns a DataView). You can't directly set SelectedItem to a DataRow instance, you have to set it to a DataRowView instance. Unfortunately there's no easy way to obtain a DataRowView from a DataRow.
You would do better to just do all of your interactions through a DataRowView. This will allow you to set SelectedItem explicitly.
You cannot use the SelectedValue property, you must use SelectedItem for this.
First of all thank you Adam Robinson, I'm sure your answer was correct, but it just wasn't what I wanted to hear. I solved my problem in a different way and I think it may be useful to someone else, so I am posting it here.
What I did was I created a new class, in my case I named it ListObject, which had a property DataRow (as you will see later it works for other types too, I just used this since this is what I actually wanted as my Item value property). It also overrides methods:
String ToString()
bool Equals(object obj)
int GetHashCode() --is not needed in my case, however Visual Studio
warns you it should be overridden.
The idea was that I could fill ComboBox.Items collections with objects of my own class, display a custom string (if I had not worked it out like this, my next question on Stack overflow would probably be about customizing DisplayMembers when reading items from a DataRow) and compare only one class's item (in my case DataRow).
So here is the code and it works great (at least for what I wanted to do with it).
public class ListObject
{
public DataRow element;
public String DisplayObject = null;
public ListObject(DataRow dr)
{
element = dr;
}
public ListObject(DataRow dr, String dspObject)
{
element = dr;
DisplayObject = dspObject;
}
public override String ToString()
{
if (DisplayObject == null) throw new Exception("DisplayObject property was not set.");
return element[DisplayObject].ToString();
}
public override bool Equals(object obj)
{
if (obj.GetType() == typeof(ListObject))
return Equals(((ListObject)obj).element, this.element);
else return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
In my case it works great since I can just fill the ComboBox's with a foreach statement:
dtUsers.ReadXml(Program.Settings.xmlInputUsers);
foreach(DataRow dr in dtUsers.Rows)
{
cmbUser.Items.Add(new ListObject(dr, "Name"));
}
And when I get the DataRow I want selected I just do this:
cmbUser.SelectedItem = new ListObject(dlg.SelectedDataRow);
Where I don't have to worry about the DisplayMember etc, because only DataRow's will be compared, and your display parameters will still be set from when you filled ComboBox.Items collection. Also since toString method is overridden you can really customize your output.
Creating this class was only possible because of msdn article on ComboBox.SelectedItem Property in which it was noted, that SelectedItem property works using the IndexOf method. This method uses the Equals method to determine equality.
This is the most simple way to get DataTable to a combobox
private void load() {
DataTable dt = // get data from DB
comboBox1.ValueMember = null; // allows you to get all fields in the obj to combobox
comboBox1.DisplayMember = "ccType";//label displayed from dt
comboBox1.DataSource = dt;
}
//to test
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
DataRowView current = (DataRowView)comboBox1.SelectedValue;
string drs = current.Row["ID"].ToString();
}
I have a ComboBox whose items are set using the DataSource property. The DataSource is a collection of a custom object (that has a string property 'Value' and int property 'Id'). In the initialise controls, I set the DisplayMember as Value and ValueMember as Id. Now I tried to clear the DataSource by calling,
myComboBox.DataSource = null;
When I did that, my DisplayMember is reset to "" automatically. Am I clearing the DataSource properly ?? Is that the way I should behave ???
I can reproduce it... it isn't something I would have expected, but it looks like you'll simply have to set the DisplayMember back afterwards.
Looking in reflector, this is quite intentional:
if (value == null)
{
this.DisplayMember = "";
}
Not sure of the reasoning behind that, but simply:
string oldDisplayMember = cbo.DisplayMember;
cbo.DataSource = null;
cbo.DisplayMember = oldDisplayMember;
Not pretty, but it'll work.
When there is an Exception thrown or if the Datasource value is null, then the Displaymember is set to an empty string.
Using a .NET code decompiler, there are comments in the code about how this works. I'll try to paraphrase.
Exceptions may be thrown in the following circumstances:
Application code on DataSourceChanged
During binding when the data is being formatted for display
If the DisplayMember value isn't valid in the new Datasource.
The comment also mentions that the actual exception is "swallowed" to keep from breaking expected behavior.
I personally ran into this behavior and since the exception isn't thrown it's difficult to figure out which of these conditions caused the reset. There is probably a better way but for now I'm using this in my custom control.
The Datasource property is valid when setting the DisplayMember after it's been reset so I'm really not sure about why it's failing :
public new object DataSource
{
get { return base.DataSource; }
set
{
string displayMem = this.DisplayMember;
base.DataSource = value;
if (string.IsNullOrEmpty(this.DisplayMember) && string.IsNullOrEmpty(displayMem))
this.DisplayMember = displayMem;
DetermineDropDownWidth();
}
}