-1

Can't figure out why this won't work. I get the same "Specified Cast is Invalid" error message. New to C#, be kind. It fails at the if(!((int)WrkRow["ManualWeight"] == 1 | etc. line. I tried a few variations of code, not all pasted here. ManualWeight is a number field in the table.

              if (dt.Rows.Count > 0)
            {
                DataRow WrkRow = dt.Rows[0];    // ds.Tables(0).Rows(0)
                if (mod1.IsTareout == true)
                    trim = (string)WrkRow["Trucker"];
                sBarcode = $"{trim.Trim()}{(string)WrkRow["TruckNo"]} ";

                XRSwatLaserCert rSwatLaserCert = new XRSwatLaserCert();
                rSwatLaserCert.DataSource = dt;

                DevExpress.XtraReports.UI.ReportPrintTool rpt = new DevExpress.XtraReports.UI.ReportPrintTool(rSwatLaserCert);
                {
                    XRBarCode XrBCTareOut = new XRBarCode();
                    rSwatLaserCert.XrBCTareOut = new XRBarCode
                    {
                        Text = sBarcode
                    };
                    if (!((int)WrkRow["ManualWeight"] == 1 | (int)WrkRow["ManualWeight"] == 3))
                    {
                        rSwatLaserCert.XrLabelManualGross1.Visible = false;
                        rSwatLaserCert.XrLabelManualGross2.Visible = false;
                        rSwatLaserCert.XrLabelManualGross3.Visible = false;
                    }

2nd Try:

            if (dt.Rows.Count > 0)
            {
                DataRow WrkRow = dt.Rows[0];    // ds.Tables(0).Rows(0)
                if (mod1.IsTareout == true)
                    trim = (string)WrkRow["Trucker"];
                sBarcode = $"{trim.Trim()}{(string)WrkRow["TruckNo"]} ";

                XRSwatLaserCert rSwatLaserCert = new XRSwatLaserCert();
                rSwatLaserCert.DataSource = dt;

                DevExpress.XtraReports.UI.ReportPrintTool rpt = new DevExpress.XtraReports.UI.ReportPrintTool(rSwatLaserCert);
                {
                    XRBarCode XrBCTareOut = new XRBarCode();
                    rSwatLaserCert.XrBCTareOut = new XRBarCode
                    {
                        Text = sBarcode
                    };
                    if (WrkRow.Field<int>("ManualWeight") != 1 | (int)WrkRow.Field<int>("ManualWeight") != 3)
                    {
                        rSwatLaserCert.XrLabelManualGross1.Visible = false;
                        rSwatLaserCert.XrLabelManualGross2.Visible = false;
                        rSwatLaserCert.XrLabelManualGross3.Visible = false;
                    }

3rd try:

                if (dt.Rows.Count > 0)
            {
                DataRow WrkRow = dt.Rows[0];    // ds.Tables(0).Rows(0)
                if (mod1.IsTareout == true)
                    trim = (string)WrkRow["Trucker"];
                sBarcode = $"{trim.Trim()}{(string)WrkRow["TruckNo"]} ";

                XRSwatLaserCert rSwatLaserCert = new XRSwatLaserCert();
                rSwatLaserCert.DataSource = dt;

               ReportPrintTool rpt = new ReportPrintTool(rSwatLaserCert);
                {
                    XRBarCode XrBCTareOut = new XRBarCode();
                    rSwatLaserCert.XrBCTareOut = new XRBarCode
                    {
                        Text = sBarcode
                    };
                    var manweight = WrkRow.Field<int>("ManualWeight");
                    if (manweight != 1 | manweight == 3)
                    {
                        rSwatLaserCert.XrLabelManualGross1.Visible = false;
                        rSwatLaserCert.XrLabelManualGross2.Visible = false;
                        rSwatLaserCert.XrLabelManualGross3.Visible = false;
                    }
4
  • 1
    In all likelihood, WrkRow["ManualWeight"] is not an int. The data in controls like that are all objects, so Value Type instances (like ints) are boxed. When you unbox a value, you need to unbox it to exactly the right type. If it's a long (like 10L) or a decimal (like 10m), you can't just cast it to an int Commented Dec 1, 2021 at 0:35
  • ManualWeight is a number field in the table - c# doesn't have a number data type; that sounds like a database thing-we need to know the c# type it's mapped as. If you created the column manually, Show us the dt.Columns.Add("ManualWeight", ...) or if the datatable was created by filling from a database source, show us the result of calling dt.Columns["ManualWeight"].DataType in the immediate window during a debug session Commented Dec 1, 2021 at 6:59
  • Fill your table, pause in the debugger, put dt.Columns["ManualWeight"].DataType into the Immediate window, and press return, wait a short moment and read the garbage.. It'll be something like blah blah System.Decimal blah blah which will mean you need to do (decimal)WrkRow["ManualWeight"] rather than (int)WrkRow["ManualWeight"] - when you've got a primitive inside an object you need to get out using an exact cast to what it truly is. If, e.g, it was a decimal inside an object and you wanted it as an int, you'd actually have to do (int)(decimal)WrkRow["ManualWeight"] Commented Dec 1, 2021 at 17:45
  • @CaiusJard Thanks, that is frustrating that people do that. We have a different issue that is more pressing today to fix. But hopefully this afternoon I will try yours and others suggestions. Thank you for your help and I will let you know if it works. Commented Dec 1, 2021 at 18:03

2 Answers 2

0

Take a look at this image, there's a lot going on in it, but hopefully it helps make sense of stuff:

enter image description here

Quick datatable, with a string, int and decimal; John's 20 years old and weighs 10.123 whatevers

When a datatable stores data in its rows, each row is effectively an array of object which means that any time you get a value of a particular column out, it comes out looking like it's an object

See where i've pulled var johnWeight - I used var to let C# decide the type, so I'm not misleading the witness. Take a look in the Locals window (bottom left) - the type is object{decimal} - this means it's a decimal, but boxed inside an object

To get it out as a decimal 10.123 we have to cast using (decimal). This is the only thing you can do at this stage; you can't strip the object wrapping off using any other type, not even one the decimal can be converted to. Check out the decimal johnWeightDecimal = (decimal)johnRow["Weight"] line; that's stripping off the object wrapping and getting the decimal value out. You can see in the locals window that it's a decimal in the type column

If you want it as an int even though it's truly a decimal and wrapped inside object, you first have to pull the object wrapping off using a cast to the true type (decimal) and then cast it again to int using (int). That's the decimal johnWeightInt = (int)(decimal)johnRow["Weight"] line..


So, if you don't know what type your item is, you can either dump it into the Immediate Window (see lower right of screenshot), or you can navigate the Locals window and expand the tree, find the Columns collection, expand it, find the entries, check their DataType..

enter image description here

All this adds up to the reason why plain DataTables are a massive pain in the ass to work with.. There is a solution:

  • Add a DataSet type of file to your project List item
  • Open it, right click, Add a DataTable to it, Add Columns to the datatable, set their datatype enter image description here
  • Now you can just use it like any other reasonable class, that has named properties: enter image description here

.. none of this casting casting casting tedium. dt[0].Weight, not (decimal)dt.Rows[0]["Weight"]

Critically, a PersonDataTable is still a DataTable (it inherits from it) so you can e.g. pass it to some data adapter that is doing SELECT Name, Age, Weight FROM users

var dt = new PersonDataTable();
someDataAdapter.Fill(dt);

There's actually a whole ecosystem within a DataSet to generate type specific DataAdapters too, but that's a bit out of scope for the post

Sign up to request clarification or add additional context in comments.

2 Comments

if (!((decimal)WrkRow["ManualWeight"] == 1 | (decimal)WrkRow["ManualWeight"] == 3)) This did the trick. Thank you!
Caius, I would also like to thank for showing me that you can really drill down to see the dat types in the datatable. It will be very useful going forward. link
0
  1. Can you check to see if that column value is null?

  2. Just to be safe, can you convert it to string and use Convert.ToInt32 method?

  3. Can you make a weight variable so you can debug and hover over it to see what it is?

     if(!WrkRow.IsNull("ManualWeight"))
     {
         var weight = Convert.ToInt32(WrkRow["ManualWeight"].ToString());
    
         if(weight == 1 || weight == 3)
         {
             ....
         }
     }
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.