-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;
                    }
CircleDot
  • 15
  • 7
  • 1
    In all likelihood, `WrkRow["ManualWeight"]` is not an `int`. The data in controls like that are all `object`s, so _Value Type_ instances (like `int`s) 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 – Flydog57 Dec 01 '21 at 00: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 – Caius Jard Dec 01 '21 at 06: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"]` – Caius Jard Dec 01 '21 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. – CircleDot Dec 01 '21 at 18:03

2 Answers2

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

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • 1
    `if (!((decimal)WrkRow["ManualWeight"] == 1 | (decimal)WrkRow["ManualWeight"] == 3))` This did the trick. Thank you! – CircleDot Dec 02 '21 at 18:09
  • 1
    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](https://i.imgur.com/KbrVwZR.png) – CircleDot Dec 02 '21 at 18:11
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)
         {
             ....
         }
     }