Passing Text & Value in ComboBox - c#

I've tried to make my combobox pass a text and then a value. But i can't get the value.
DropDownList1.Items.Add(new ListItem("abc", 23));
DropDownList1.Items.Add(new ListItem("def", 56));
Then I try get the value when i've selected any of these in the Combobox
string text = DropDownList1.SelectedItem.ToString();
string value = DropDownList1.SelectedValue.ToString();
this.label5.Text = text + " with value: " + value;
This results in a crash with following error code:
"An unhandled exception of type 'System.NullReferenceException' occurred in WindowsFormsApplication1.exe
Additional information: Object reference not set to an instance of an object."
If I just use the "text" variable, everything is fine.
What am I missing?
EDIT: I know that I get null and that will help me not crash, but why is the value not passed on to / from the ComboBox? Thanks in advanced
SOLUTION:
This is how I managed to solve it.
var source = new Dictionary<string, int>();
source.Add("College", 100);
source.Add("T-shirt", 54);
DropDownList1.DataSource = source.ToList();
DropDownList1.DisplayMember = "Key";
DropDownList1.ValueMember = "Value";
And then
private void button1_Click_1(object sender, EventArgs e)
{
var selectedItem = DropDownList1.Text;
if (DropDownList1.SelectedValue == null)
{
return;
}
string value = DropDownList1.SelectedValue.ToString();
//[etc…]
this.label5.Text = "Cloth:" + selectedItem + " costs " + value;
}
Hope this can help anyone.
Thanks all for help!

I've done this quite a long ago. But I think you need to use it like this:
var selectedItem = DropDownList1.SelectedItem;
if (selectedItem != null)
{
string text = selectedItem.Text;
string value = selectedItem.Value;
}

You may need to bind this data before you use it, try it:
myDropdown.DataBind()
Just after adding your items and it may solve it, I think you can find tons and tons of tutorials about it, just Google it

You should add a check to check of i = null like this:
label1.text = DropDownList1.selectedItem.Value != null ? DropDownList1.selectedItem.Text + " with value: " + DropDownList1.selectedItem.Value : label1.text;
This should do the trick it checks if i != null;
you're getting the error because you cant an empty variable with +

// Check whether your combobox is selected or not
if (DropDownList1.SelectedIndex != -1)
{
string text = DropDownList1.SelectedItem.ToString();
string value = DropDownList1.SelectedValue.ToString();
this.label5.Text = text + " with value: " + value;
}
else
{
// message to select option
}
Please note- We have ComboBox in Windows Application and Dropdownlist in Asp.net.

You may need to bind this data before you use it, try it:
myDropdown.DataBind()
Just after adding your items and it may solve it, I think you can find tons and tons of tutorials about it, just Google it
I think there may be none item selected, and you're calling .ToString() in a null value, I cant figure it out without more context, how are you trying to get the selected value?

Since you haven't said which line the exception is thrown on, so it's a bit of a shot in the dark. However:
string value = DropDownList1.SelectedValue.ToString();
DropDownList1.SelectedValue might be null, in which case trying to call ToString() on it would cause a NullReferenceException. Try:
if (DropDownList1.SelectedValue == null)
return;
var value = DropDownList1.SelectedValue;
this.label5.Text = String.Format("{0} with value: {1}", text, value);
//[etc…]
Update:
Assuming that your combobox isn't databound since you are adding items in memory, you need to set the default selected value as well. You would need to find the object's index in the Items collection on your form and then set the SelectedIndex property to the appropriate index.
DropDownList1.Items.Add(new ListItem("abc", 23));
DropDownList1.Items.Add(new ListItem("def", 56));
DropDownList1.SelectedIndex = DropDownList1.Items.IndexOf("abc");
Keep in mind that the IndexOf function may throw an ArgumentException if the item is not in the collection.

Related

How to check if text value is in a control's DataSource which contains DataRowViews?

On validating a ComboBox I'm trying to check if the value in the ComboBox is in the list of values that is databound to said ComboBox.
The datasource is a BindingSource and the underlying items are of type DataRowView.
So I can't figure out how to compare the combobox's value to the 'Person' field of the DataSource's DataRowView
Also before someone suggests just setting the DropDownStyle to DropDownList, that is not an option for this case.
What I have tried:
private void ddPerson_Validating(object sender, CancelEventArgs e)
{
ComboBox cmbo = sender as ComboBox;
if (!string.IsNullOrWhiteSpace(ddPerson.Text))
{
if (cmbo.Items.Contains(ddPerson.Text))
{
errorProvider1.SetError(cmbo, "");
}
else
{
errorProvider1.SetError(cmbo, "\"" + person.Text + "\" is not in the list of accepted values");
}
}
else
{
errorProvider1.SetError(cmbo, cmbo.DisplayMember + " is required");
}
}
I've also tried
if (personBindingSource.Contains(ddPerson.Text))
The above two solutions I tried don't work because personBindingSource and cmbo.Items are just lists of DataRowView objects.
And from here https://stackoverflow.com/a/24126821/3490417
I tried
if (cmbo.Items.Cast<DataRowView>().Select(x => Convert.ToString(x["Person"]).Contains(ddPerson.Text))
This doesn't compile with error "Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'bool'
EDIT:
I found an alternate way of checking if the combobox's value is in the combobox's bindingsource. Though I ended up using mm8's solution as it is cleaner.
int found = personBindingSource.Find("Person", ddPerson.Text);
if (found < 0)
{ errorProvider1.SetError(cmbo, "\"" + person.Text + "\"
is not in the list of accepted values"); }
Try this:
if (cmbo.Items.OfType<DataRowView>().Any(x => x["Person"]?.ToString() == ddPerson.Text))
The following code will work regardless of the data-bound item type and the display member property:
var isValid = cmbo.Items.Cast<Object>().Any(x=>cmbo.GetItemText(x) == ddPerson.Text);

How to Avoid Updating item searched by Dictionary?

In .NET WinForms C# app, I have a Dictionary<string, RefItemDetails> collection named listItems. I store data in it on start of the app. In a static class I have as follows:
// listItems is populated bt reading a file.
// No other operations are performed on it, except finding an item.
public static Dictionary<string, RefItemDetails> itemsList;
// Find RefItemDetails of barcode
public static RefItemDetails FindRefItem(string barcode)
{
RefItemDetails itemDet = null;
try
{
//if (itemsList.TryGetValue(barcode, out itemDet) == false)
// System.Diagnostics.Debug.WriteLine("Barcode " + barcode + " not found in Items");
//itemDet = itemsList.First(item => item.Key == barcode);//.First(item => item.Barcode == barcode);
if (itemsList.ContainsKey(barcode))
itemDet = itemsList[barcode];
}
catch (Exception)
{
itemDet = null;
}
return itemDet;
}
For retrieving an item from listItems in another class, I use :
refScannedItem = null;
// Get Unit Barcode & Search RefItem of it
refScannedItem = UtilityLibrary.FindRefItem(boxItem.UnitBarcode.Trim());
// Display BOX item details
refScannedItem.Barcode = boxItem.BoxBarcode.Trim();
refScannedItem.Description = "BOX of " + boxItem.Quantity + " " + refScannedItem.Description;
refScannedItem.Retail *= boxItem.Quantity;
refScannedItem.CurrentCost *= boxItem.Quantity;
Here what happens above is, I search for an item & I get it "refScannedItem" and I append the Description of it by "BOX of " + boxItem.Quantity + " " + refScannedItem.Description; . So if the original Description was "Aquafina", I make it "BOXof 10 Aquafina". The nest time I scan the same product, I find the product, but now its descrption has become "Box of 10 Aquafina", so my line of setting Description turns to "BOX of 10 BOX of 10 Aquafina". The same goes on like "BOX of 10 BOX of 10 BOX of 10 Aquafina" and so on.
As you cna see in my find code, I had initially used TryGetValue, then tried using LINQ, then tried using ContainsKey, but in all of them why does the value of listItem get updated.
I understand that as TryGetValue has out parameter, so the value is passed as a reference, and then it will be chnaged. But in listItems[key] also updates it !!! How can I avoid this to happen ? I had selected Dictionary collection for easy & fast searching, but this part gives a lot of problems and a big bug too on my app. I couldn't find nay solution where the receive the value but shouldn't be updated. All articles shows how to search & update it.
Kindly suggest a solution for the above. Any help is highly appreciated.
Thanks
You return a pointer to the item contained in your Dictionary, so it makes sense that any manipulations you make to this Object will be stored in the original Dictionary object.
What you want to do is, in FindRefItem, return a pointer to a copy of your RefItemDetails object.
An easy way to do this would be to write a new constructor.
Something like:
public RefItemDetails(RefItemDetails original)
{
this.Barcode = original.Barcode ;
this.Description = original.Description ;
this.Retail = original.Retail ;
this.CurrentCost = original.CurrentCost ;
//Set any other properties here
}
and then replace return itemDet; with return new RefItemDetails(itemDet);
I think you are going about this the wrong way.
You shouldn't have a writeable Description property that you update whenever the quantity changes.
Instead, I think you should have a separate Name property which contains the name of the item (e.g. Aquafina) and a dynamically-created readonly Description property like so:
public string Description
{
get
{
return string.Format("Box of {0} {1}", Quantity, Name);
}
}
Or something along similar lines.
This should do the trick:
if (!refScannedItem.Description.StartsWith("BOX of "))
{
refScannedItem.Description = "BOX of " + boxItem.Quantity + " " + refScannedItem.Description;
}
You are getting an object from a Dictionary - and then changing it, so of course it's properties will change in the Dictionary as well ... you haven't cloned it so why would you be taking a copy?
The solution is quite simply not to change the values of the item and use the amended text in a different way:
var amendedDescription = "BOX of " + boxItem.Quantity + " " + refScannedItem.Description;
Looks like you need to make a copy of the RefItemDetails to make modifications to after you get it back from the call to UtilityLibrary.FindRefItem(boxItem.UnitBarcode.Trim())

Not able to import specific excel cell to a texbox: Object reference not set to an instance of an object thrown C#

Hi I am trying to import value of a specific excel cell to a textbox on the form. The value will appear as soon as the form loads. Now this cell can be null and I am taking care of the null value but it is throwing an exception and going into catch everytime a null value is passed. Here is the snippet of my code:
try
{
var v;
if( oSheet.Cells[3, 4].Value2 != null)
{
v = Sheet.Cells[3, 4].Value2;
var s = Convert.ToString(v);
textBox1 = string.Format("{0:N2}", s);
}
else
{
v = 0;
var s = Convert.ToString(v);
textBox1 = string.Format("{0:N2}", v);
}
}
catch(Exception)
{
string errorMessage = "Data cannot be retrieved from the strats file ;
MessageBox.Show(errorMessage);
}
The catch is showing this exception "object reference not set to an instance of an object". I am taking care or the null oSheet.Range.Value2, then why is it throwing error as soon as it reaches the if statement ? Can someone please help I am frustrated with this problem since quite few days
Have you initialize the "oSheet" object?
if( oSheet.Cells[3, 4].Value2 != null)
{
//I think you have a spelling mistake, oSheet.Cells[3, 4] vs Sheet.Cells[3,4]
v = Sheet.Cells[3, 4].Value2;
....
}

ComboBox.ObjectCollection doesn't update if the new value's string representation is case-insensitively equal to the current value

If I try to change a value in a ComboBox's Items, it will only actually update if the new value is different from the current value after a case-insensitive compare.
Let's make a ComboBox with one item:
ComboBox cboBox = new ComboBox();
cboBox.Items.Add("Apple");
The following code will make the ComboBox still show "Apple", even though the string should look different:
cboBox.Items[0] = "APPLE";
And the naive workaround that I've been using, which will make it display correctly:
cboBox.Items[0] = "";
cboBox.Items[0] = "APPLE";
I wanted to figure out how this was happening, so I dug around with a reflector and found this. This is the ComboBox.ObjectCollection.SetItemInternal method that gets called when you try to modify a value:
internal void SetItemInternal(int index, object value)
{
...
this.InnerList[index] = value;
if (this.owner.IsHandleCreated)
{
bool flag = index == this.owner.SelectedIndex;
if (string.Compare(this.owner.GetItemText(value), this.owner.NativeGetItemText(index), true, CultureInfo.CurrentCulture) != 0)
{
this.owner.NativeRemoveAt(index);
this.owner.NativeInsert(index, value);
if (flag)
{
this.owner.SelectedIndex = index;
this.owner.UpdateText();
}
if (this.owner.AutoCompleteSource == AutoCompleteSource.ListItems)
{
this.owner.SetAutoComplete(false, false);
return;
}
}
else
{
if (flag)
{
this.owner.OnSelectedItemChanged(EventArgs.Empty);
this.owner.OnSelectedIndexChanged(EventArgs.Empty);
}
}
}
}
That true in string.Compare is telling it to ignore the case of the string. Why was this method chosen for deciding whether or not to update the value? And why didn't they expose the case sensitivity?
Is there an alternative way to update an item in an ObjectCollection so that I don't have to guess whether or not it actually gets updated?
EDIT: I should note that the DropDownStyle is set to DropDownList: this is a read-only ComboBox that occasionally needs to be updated due to actions elsewhere in the program.
Try this, add a SelectedIndexChanged event, and inside it put:
int index = cboBox.SelectedIndex;
if (index - 1 >= 0) {
cboBox.SelectedIndex = index - 1;
cboBox.SelectedIndex = index;
}
else if (index + 1 < cboBox.InnerList.Count) {
cboBox.SelectedIndex = index + 1;
cboBox.SelectedIndex = index;
}
This is probably as "naive" as your work around, but maybe worth a try?
After submitting a report to the MSDN, it was marked as "by-design" and nothing more, so that's that.

How to set Selected item of ComboBox in C# Windows Forms?

I am trying to set selected item of comboBox on click event of DataGrid, but I could not. I have googled and tried different ways but without success.
For me SelectedIndex is working, but I could not find the index of items in ComboBox, so I could not select the item.
Not working code:
for (int i = 0; i < cmbVendor.Items.Count; i++)
if (cmbVendor.Items[i].ToString() == Convert.ToString(gridView1.GetFocusedRowCellValue("vVendor")))
{
cmbVendor.SelectedIndex = i;
break;
}
You can get your item index by the .Items.IndexOf() method. Try this:
comboBox1.SelectedIndex = comboBox1.Items.IndexOf(gridView1.GetFocusedRowCellValue("vVendor"));
You don't need to iterate.
You can find more information in Stack Overflow question How do I set the selected item in a comboBox to match my string using C#?.
The following is working for me perfectly. Pass any value or Text which is available in the combobox.
comboBox1.SelectedIndex = comboBox1.FindString(<combobox value OR Text in string formate>);
You have it in your if:
cmbVendor.SelectedItem = cmbVendor.Items[i];
At last I found it out. It's:
cmbVendor.Text = Convert.ToString(gridView1.GetFocusedRowCellValue("vVendor"));
The SelectedText property is for the selected portion of the editable text in the textbox part of the combo box.
If you have set ValueMember property for the ComboBox control, you can simply assingn the Value to the ComboBox control's SelectedValue property. You don't have to find the index explicitly.
Here's an example:
public class Vendor{
public int VendorId {get; set;}
public string VendorName {get; set;}
}
// Inside your function
var comboboxData = new List<Vendor>(){
new Vendor(){ vendorId = 1, vendorName = "Vendor1" },
new Vendor(){ vendorId = 2, vendorName = "Vendor2" }
}
cmbVendor.DataSource = comboboxData;
cmbVendor.DisplayMember = "VendorName";
cmbVendor.ValueMember = "ValueId";
// Now, to change your selected index to the ComboBox item with ValueId of 2, you can simply do:
cmbVendor.SelectedValue = 2;
Assuming gridView1.GetFocusedRowCellValue("vVendor") really works as expected, the following code should fix the problem.
string selected = Convert.ToString(gridView1.GetFocusedRowCellValue("vVendor"));
foreach ( var item in cmbVendor.Items )
{
if (string.Compare(item.ToString(), selected, StringComparison.OrdinalIgnoreCase) == 0)
{
cmbVendor.SelectedItem = item;
break;
}
}
The original code had multiple calls to gridView1.GetFocusedRowCellValue("vVendor"), whereas you only need one.
The suggested "comboBox1.Items.IndexOf(" assumes too much about the content of cmbVendor.Items.
I had a similar problem and worked it out partially with the help of the other answers here. First, my particular problem was that
combobox1.SelectedItem = myItem;
was not working as expected. The root cause was that myItem was an object from a group which was effectively the same list as the items in the combobox, but it was actually a copy of those items. So myItem was identical to a valid entry, but itself was not a valid object from the combobox1 container.
The solution was to use SelectedIndex instead of SelectedItem, like this:
combobox1.SelectedIndex = get_combobox_index(myItem);
where
private int get_combobox_index(ItemClass myItem)
{
int i = 0;
var lst = combobox1.Items.Cast<ItemClass >();
foreach (var s in lst)
{
if (s.Id == myItem.Id)
return i;
i++;
}
return 0;
}
ComboBox1.SelectedIndex= ComboBox1.FindString("Matching String From DataGrid Cell value")
Try this this will work fine in C# Windows application
this works for me.....
string displayMember = ComboBox.DataSource.To<DataTable>().Select("valueMemberColumn = '" + value + "'")[0]["displayMember"].ToString();
ComboBox.FindItemExact(displayMember, true).Selected = true;

Categories