Unable to cast Combobox.SelectedValue - c#

My code goes like this for simple practise problem which i am trying to build. I come across
Invalid Cast Exception. Specified Cast is not valid.
public Form1()
{
Combobox1.Datasource = foo.bar.dataset.tables[0];
Combobox1.DisplayMember = "Name";
Combobox1.ValueMember = "ID";
}
private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
NewClass P2 = new NewClass;
P2.Filter.Id = (long)Combobox1.SelectedValue;
}
Can anyone tell me why is this happening and how to go about solving it even though I have typecasted Combobox1.SelectedValue object?

Maybe this will help:
P2.Filter.Id = Convert.ToInt64(Combobox1.SelectedValue);
According to your comment this might help:
P2.Filter.Id = Convert.ToInt64((Combobox1.SelectedValue as DataRowView).Item[0]);

I'm not sure why this happens, maybe someone can help me on that but I would prefer going.
P2.Filter.Id = Convert.ToInt64(Combobox1.SelectedValue);
That always works for me when I have this issue.

ComboBox.SelectedValue is obviously not a long. You should do whatever is required to change its type; most probably this would be
P2.Filter.Id = Convert.ToInt64(ComboBox1.SelectedValue);

Check the object reference before you cast SelectedValue.
long value=0l;
if (comboBox1.SelectedValue != null)
{
value=long.Parse(comboBox1.SelectedValue.ToString());
}
You can use SelectedItem property which will returns the reference of DataRowView (row).
DataRowView row = comboBox1.SelectedItem as DataRowView ;
if (row != null){
MessageBox.Show("value " + row[0] + " " + row[1]);
}

Casting a string to long is mal-casting. SelectedValue is supposed to return a string that needs Convert.ToLong to operate on

Convert.ToInt64(Combobox1.SelectedValue)

Rather try something like
Convert.ToInt64
Converts a specified value to a 64-bit signed integer.
At some later stage you might also want to take a look at using
Int64.TryParse Method
Converts the string representation of a number to its 64-bit signed
integer equivalent. A return value indicates whether the conversion
succeeded or failed.
or Int64.Parse Method
Converts the string representation of a number to its 64-bit signed
integer equivalent.

Thickness t = new Thickness(0);
if (value != null)
{
t= new Thickness(System.Convert.ToInt64(((System.Windows.Controls.ComboBoxItem)value).GetValue(System.Windows.Controls.ComboBoxItem.ContentProperty)));
}
return t;

Related

Winform datagridview numeric sorting [duplicate]

This question is closely related to these two (this and this) but I don't think they give a satisfying answer.
I have a DataGridView (i.e. a table) with several columns (DataGridViewTextBoxColumn) of different data types: string, integers and floats. When I click on their respective header, each should be sorted according to their type: string alphabetically and numerical values numerically. I have, simply put, the following code:
private System.Windows.Forms.DataGridView grid;
private System.Windows.Forms.DataGridViewTextBoxColumn stringColumn;
private System.Windows.Forms.DataGridViewTextBoxColumn doubleColumn;
private System.Windows.Forms.DataGridViewTextBoxColumn intColumn;
stringColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
doubleColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
intColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
grid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
stringColumn,
doubleColumn,
intColumn});
However, since the default representation is string, the numerical values also get sorted alphabetically, for example like this:
1, 11, 2, 3, 42, 5
Apparently, as an easy way of getting around this, according some threads (e.g. here and here), the following should work immediately solve the problem:
doubleColumn.ValueType = typeof(double);
intColumn.ValueType = typeof(int);
However, this solution simply doesn't work in my project: values are still sorted alphabetically. So the question is: why not? In the Debugger, I could see that the value type actually changed to (in the double case) System.Double, so something is happening at least. But how can I make sure that it actually sorts it accordingly, without writing my own sorter?
You can handle the event SortCompare to change how the sorting is done, like this:
private void dataGridView1_SortCompare(object sender, DataGridViewSortCompareEventArgs e) {
//Suppose your interested column has index 1
if (e.Column.Index == 1){
e.SortResult = int.Parse(e.CellValue1.ToString()).CompareTo(int.Parse(e.CellValue2.ToString()));
e.Handled = true;//pass by the default sorting
}
}
NOTE: The above code supposes your cell values are convertible to int.
You said your DataGridView doesn't have DataSource assigned, that means you Add the rows manually, so I think you should use numeric values instead of string for your cells. That would make the sorting work as you want.
If you are using a DataTable then you have to set the DataType on the DataColumn. Setting ValueType on the DataGridViewTextBoxColumn won't help.
You can set it when creating it:
table.Columns.Add("Number", typeof(int));
Changing column from string to int32 might be helpful:
for (int i = 0; i < tableDataGridView.Rows.Count; i++) {
DateTime dt = Convert.ToDateTime(tableDataGridView.Rows[i].Cells[9].Value.ToString());
DateTime dtnow = DateTime.Now;
TimeSpan ts = dtnow.Subtract(dt);
tableDataGridView.Rows[i].Cells[1].Value = Convert.ToInt32( ts.Days.ToString());
}
tableDataGridView.Sort(tableDataGridView.Columns[1], ListSortDirection.Descending);
For me, it works. I hope it will help.
Setting your column ValueType to typeof(int) will work, just remember to make sure you put integers into that column. If the rest of your data contains strings, it can be easy to forget to convert your number from a string to an int.
https://www.youtube.com/watch?v=kKeTRPSLxX8 watch this video, it helps a lot
Copying the code from that video:
Private Sub dgvDailySales_SortCompare(sender As Object, e As DataGridViewSortCompareEventArgs) Handles dgvDailySales.SortCompare
Try
Dim dval1, dval2 As Double
If Not Double.TryParse(e.CellValue1.ToString, dval1) Then Return
If Not Double.TryParse(e.CellValue2.ToString, dval2) Then Return
If dval1 = dval2 Then
e.SortResult = 0
ElseIf dval2 > dval1 Then
e.SortResult = -1
ElseIf dval1 > dval2 Then
e.SortResult = 1
End If
e.Handled = True
Catch ex As Exception
MsgBox(ex.Message, vbCritical)
End Try
End Sub

Specified cast is not valid while accessing column value

I am finding records in datatable. If the record matches then I want to compare value in the datarow and do some operation. Please see my code below for better explanation,
foreach (DataRow row2 in dtTo.Rows)
{
DataRow[] match = dtReturn.Select("Id = " + row2["Id"]);
if (match.Length > 0)
{
if (match[0]["boolInt"] == 1) // Getting error on this line
{
match[0]["NewValues"] = "";
}
}
}
I was getting error on below line
if (match[0]["boolInt"] == 1)
Then resharper suggested me to cast to bool. so I changed above line to
if( (bool) (match[0]["bClosed"] = 1))
But when I run the project I get run time error as "Specified cast is not valid" on above line.
In immediate window I get value as 1 when I type ,
(match[0]["bClosed"]
What should i do to get rid of this error?
According this:
No there wont be null. The field is tinyint
you code should look like this (AFAIR, tinyint in SQL server matches byte in CLR):
if ((byte)(match[0]["boolInt"]) == 1)
{
}
If you know the field type, there's no need to call Convert methods. The faster way is to cast directly to that known type.
You need to convert the value to int. You can do it like this:
if (Convert.ToInt32(match[0]["boolInt"]) == 1)
But if the column contains a value that can't be casted you wil get an error.
A better aproach would be:
int number;
bool result = Int32.TryParse(match[0]["boolInt"], out number);
if (result && number == 1)
Try this:
if ((match[0]["boolInt"] as int?) == 1)
{
match[0]["NewValues"] = "";
}
if value is null or not valid int it won't cause exception, but should be handled anyways.

C# Split() in ListBox

listBox2 contents:
0:FirstProduct
1:ProductAgain
2:AnotherProduct
3:OkFinalProduct
What I'm trying to do, when the selected index has changed on listBox2, is to have it make my int "DBID" the value of the number before the ":".
Here's my attempt:
private void listBox2_SelectedIndexChanged(object sender, EventArgs e)
{
if (listBox2.SelectedIndex == -1)
{
return;
}
int DBID;
DBID = Convert.ToInt32(listBox3.SelectedValue.ToString().Split(":"[0]));
ShowProduct(DBID);
}
ANY help with this is greatly appreciated :)
Thanks guys
EDIT -
Sorry, yes I actually tried:
DBID = Convert.ToInt32(listBox3.SelectedValue.ToString().Split(':')[0]);
but im getting the following errors:
The best overloaded method match for string.Split(params char[])' has some invalid arguments
Argument1: cannot convert from 'string' to 'char[]
EDIT #2 -
When using:
DBID = Convert.ToInt32(listBox3.SelectedValue.ToString().Split(':')[0]);
After running the application and clicking on a different listbox item, I'm encountering this exception:
NullReferenceException was unhandled. Object reference not set to an instance of an object.
I appreciate all the help so far guys!
Try changing:
DBID = Convert.ToInt32(listBox3.SelectedValue.ToString().Split(":"[0]));
To:
DBID = Convert.ToInt32(listBox3.SelectedValue.ToString().Split(':')[0]);
Update
Try this instead. It explicitly adds a new char:
DBID = Convert.ToInt32(listBox3.SelectedValue.ToString().Split(new char[] { ':' })[0]);
DBID = Convert.ToInt32(listBox3.SelectedValue.ToString().Split(':')[0]);
A safer way will be to replace the single statement with the following code,
if (listBox3.SelectedValue != null)
{
string selectedValue = listBox3.SelectedValue.ToString();
if (!string.IsNullOrEmpty(selectedValue))
{
if (Int32.TryParse(selectedValue.Split(':')[0], NumberStyles.Integer, CultureInfo.CurrentCulture, out DBID))
{
// Process DBID
}
else
{
// Cannot convert to Int32
}
}
}
Then use breakpoints in the code, to find where the NullReferenceException is occurring.
Note that this example assumes that you are using System.Windows.Controls.ListBox or System.Windows.Forms.ListBox, and not System.Web.UI.WebControls.ListBox. In the later case, the SelectedValue is a string and not an object (as pointed out by #Srinivas Reddy Thatiparthy in another answer's comment)

Checking value from Combobox(string) without ToString C#

I'm doing a project where "ToString" is being used as a method.
private void button1_Click(object sender, EventArgs e)
{
if(cboPlaneType.SelectedItem = "Generic")
{
}
else if (cboPlaneType.SelectedIndex = "Passenger")
{
}
else if (cboPlaneType.SelectedIndex = "Fighter Jet")
{
}
}
And in this case i'm not sure what to do. As you can see I've tried a few different option but with no avail. I've also tried
if((string)cboPlaneType.SelectedItem = "Generic")
And that didn't work.
**Edit
Just to point out, SelectedValue wasn't the correct answer.
ended up being "if((string)combobox.SelectedItem == "Generic")
The equality operator in c# is ==; = is an assignment operator.
SelectedIndex will return an int representing the zero-based position of the item that is selected. (I'm guessing it returns -1 when no item is selected.)
SelectedItem can be an object of any type; if it is not a string then you can't match it by comparing with a string.
Are you saying that the objects with which the ComboBox is populated override ToString()? You should still be able to use the result of that method for comparison, because it can only return a string. Otherwise, you might be able to use SelectedValue, but this depends on what kind of ComboBox you are using and how you have set it up.
SelectedIndex is an property of type Int32.
Maybe you want to use SelectedValue instead ?

Using the conditional operator ? to check for null session variable

Take a look at this code:
System.Web.SessionState.HttpSessionState ss = HttpContext.Current.Session["pdfDocument"] ?? false;
if ((Boolean)ss)
{
Label1.Text = (String)Session["docName"];
}
Basically I want to check if HttpContext.Current.Session["pdfDocument"] is not null, and if it isn't to cast to Boolean, then check if its true or false.
I'm trying to avoid nested if statements and figured there would be a more elegant way to do it. I'm therefore only interested in answers that contain the conditional ? operator.
Any tips?
Why do you use ss variable?
What about this:
if (HttpContext.Current.Session["pdfDocument"] != null)
{
Label1.Text = (String)Session["docName"];
}
object ss = HttpContext.Current.Session["pdfDocument"] ?? false;
if ((Boolean)ss)
{
Label1.Text = (String)Session["docName"];
}
Not sure exactly what you're asking for, how about:
System.Web.SessionState.HttpSessionState ss;
Label1.Text = (Boolean)((ss = HttpContext.Current.Session["pdfDocument"]) ?? false) ? (String)Session["docName"] : Label1.Text;
Should leave ss with either a valid session or null, avoids the problem of trying to store false to ss and completely skips the subsequent 'if'. Though there's a repetition of Label1.Text.
Note: this has been edited to take account of the comment by Dave below.
The problem is that you can't do this:
SessionState.HttpSessionState ss = false;
Try putting your nested ifs into an extension method then call that instead.
HttpContext.Current.Session is an System.Web.SessionState.HttpSessionState object, which is a hash or dictionary, as some may call it, of different objects, so unless you're storing an HttpSessionState object as the "pdfDocument" location the first line is incorrect.
If you're actually storing a bool in the "pdfDocument" location which may or may not already be in this slot, you could cast that directly to a bool and null coalesce it: var ss = (bool)(HttpContext.Current.Session["pdfDocument"] ?? false);.
If you're possibly storing some other kind of object in the "pdfDocument" location you could just see if it's currently at that location by checking for null: var ss = HttpContext.Current.Session["pdfDocument"] != null;.
You can try this, though I don't know if it fits your aesthetics:
bool isPdfDocumentSet =
bool.TryParse((HttpContext.Current.Session["pdfDocument"] as string,
out isPdfDocumentSet)
? isPdfDocumentSet
: false;
EDIT: There is actually an even more concise way of doing it:
bool isPdfDocumentSet =
bool.TryParse(HttpContext.Current.Session["pdfDocument"] as string,
out isPdfDocumentSet) && isPdfDocumentSet;
I think the closest you will get to the solution taking that path is following:
System.Web.SessionState.HttpSessionState ss = HttpContext.Current.Session["pdfDocument"];
if (ss != null)
{
Label1.Text = (String)Session["docName"];
}

Categories

Resources