Christopher Kane

Ramblings of a Software Architect

Recent posts

Tags

Categories

Navigation

Pages

Archive

Blogroll

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

SOLVED: "The calling thread cannot access this object because a different thread owns it"

When writing a WPF application using MVVM I  came across this exception when throwing events up to the UI. The problem was that the source events were being thrown from a SmartCard API on a separate thread and I needed to bubble an event up to the UI to update an ObservableCollection in the ViewModel of the current Window.

The problem was I need to cast the DataContext to the correct ViewModel and in order to do that I needed to be on the UI thread. To solve the problem you need to use the Dispatcher but in a very specific way in order to do the cast. Below is the code example I used:

// Need to use the dispatcher with the new SmartCard assemblies to check if needed
// There is a warehouse selection dropdown on the left menu.  This Init() causes it to hook up to 
// the SessionSecurity.UserAuthenticationChanged event to populate that dropdown.
if (!leftMenu.Dispatcher.CheckAccess()) { // Use BeginInvoke with this delegate to pass method as parameter
// without declaring a custom delegate.
Dispatcher.BeginInvoke(new Action(() => { ((LeftMenuControlViewModel)leftMenu.DataContext).EvaluateUserState(); }), System.Windows.Threading.DispatcherPriority.Normal); } else { ((LeftMenuControlViewModel)leftMenu.DataContext).EvaluateUserState(); }
Posted: Jul 08 2010, 02:36 by ckane | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under:
Trip to Washington DC for 4th of July

If you’ve never been to our Nation’s Capital I highly recommend that you go but schedule plenty of time to walk around the National Mall. Bring plenty of water and wear tennis shoes.

Posted: Jul 07 2010, 03:49 by ckane | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under:
Axapta x++ Pick List Registration & packing slip post through code

This one is going to be a bit lengthy. We needed a way to Pick/Pack/Ship a sales order line using a single method call in Axapta. We used this code in a WCF service that allowed us to make a single call to pick, pack, and ship a single line from a sales order.

Below is the entire codebase I wrote (with comments) to accomplish this goal. If you have any questions please drop me an email.

   1: // classDeclaration
   2: class VendorIntegration_Shipment
   3: {
   4:     WMSOrderTransType_Output   wmsOrderTransType;
   5:     WMSOrderTrans              wmsOrderTrans;
   6:     DlvMode                    dlvMode;
   7:     InventTable                inventTable;
   8:     WMSRouteId                 pickListId;
   9:     PackingSlipId              packingSlipId;
  10:     CustDlvModeId              custDlvModeId;
  11:     DlvModeId                  dlvModeId;
  12:     str 10                     tradingPartner;
  13: }
  14:  
  15: // new instance method
  16: // Trading Partner: string used to determine calling vendor
  17: // PickListId: Picklist from the sales order
  18: // CustDlvModeId: Vendor's Shipping Method (we will look up ours from an xref table)
  19: void new(str 10 _tradingPartner, WMSRouteId _pickListId, CustDlvModeId _dlvMode)
  20: {
  21:     VendorIntegrationModeOfDeliveryXRef vendDlvModeXRef;
  22:     ;
  23:     // trading partner is a string value we used to determine the vendor so we can look up cross reference information
  24:     // specific to that vendor. Some vendors use different Shipping Method names than we do so we use a cross 
  25:     // reference table to store their Shipping methods to ours.
  26:     if(_tradingPartner == '' || _pickListId == '' || _dlvMode == '')
  27:     {
  28:         throw Global::error("One or more arguments were not supplied. (cstor).");
  29:     }
  30:  
  31:     tradingPartner = _tradingPartner;
  32:     pickListId = _pickListId;
  33:     // Check to see if the supplied shipping method is different
  34:     // from the Picking List.
  35:     if(WMSPickingRoute::find(_pickListId).DlvModeId != _dlvMode)
  36:     {
  37:         // Check to see if we have this shipping method
  38:         dlvMode = DlvMode::find(_dlvMode);
  39:         if(dlvMode == null)
  40:         {
  41:             // Look up the supplied shipping method in the vendorXRef table.
  42:             vendDlvModeXRef = VendorIntegrationModeOfDeliveryXRef::find(_tradingPartner, _dlvMode);
  43:             if(vendDlvModeXRef != null)
  44:             {
  45:                 //Wire it up
  46:                 dlvMode = DlvMode::find(vendDlvModeXRef.DlvModeId);
  47:             }
  48:             else
  49:             {
  50:                 throw Global::error("The supplied shipping method could not be found (VendShippingXRef).");
  51:             }
  52:         }
  53:     }
  54:     else
  55:     {
  56:         dlvMode = DlvMode::find(_dlvMode);
  57:     }
  58: }
  59:  
  60: // Primary method to kick off the PICK/PACK/SHIP
  61: // RecId: Specific record id from the WMSOrderTrans table generated AFTER PickList
  62: // Qty: Quantity to ship
  63: // InventSerialId: The serial # chosen to ship
  64: // TrackingNumbers: x++ Container of tracking numbers supplied for this shipment
  65: // ShipDate: The date of the shipment
  66: public void receiveShipmentLine(int64 _recId, int _quantity, InventSerialId _inventSerialId, container _trackingNumbers, Date _shipDate)
  67: {
  68:     ;
  69:     try
  70:     {
  71:         ttsBegin;
  72:  
  73:         // Look up the order transaction by picklist and recid
  74:         select forUpdate wmsOrderTrans where wmsOrderTrans.RecId == _recId && wmsOrderTrans.routeId == pickListId;
  75:  
  76:         // Construct the Order Trans type object
  77:         wmsOrderTransType = wmsOrderTransType::construct(wmsOrderTrans);
  78:  
  79:         // If the item is serialized, then compare and replace the inventory dimension. Custom method to check if Serialized Part
  80:         if(InventTable::isSerialized(wmsOrderTrans.itemId)) this.updatePickListLineSerial(_inventSerialId);
  81:  
  82:         // Pick the line
  83:         this.registerPickListLine();
  84:  
  85:         // Pack the line
  86:         this.registerPackingSlipLine();
  87:  
  88:         //Save the tracking numbers
  89:         this.saveTrackingNumbers(_trackingNumbers, _shipDate);
  90:  
  91:         ttsCommit;
  92:     }
  93:     catch (Exception::Error)
  94:     {
  95:         error("'Exception::Error' Unable to complete receiveShipmentLine. Transaction aborted.");
  96:     }
  97: }
  98:  
  99: // Used to update the PickList Registration
 100: private void updatePickListLineSerial(InventSerialId _inventSerialId)
 101: {
 102:     InventDim           inventDimOrig;
 103:     InventDim           inventDimNew;
 104:     ;
 105:  
 106:     // If not empty
 107:     if(_inventSerialId != '')
 108:     {
 109:         if(wmsOrderTrans != null)
 110:         {
 111:             // Look up the order transaction dimension
 112:             inventDimOrig       = InventDim::find(wmsOrderTrans.inventDimId);
 113:  
 114:             if(_inventSerialId != inventDimOrig.inventSerialId)
 115:             {
 116:                 // Find dim with the new serial number (our custom method to do the lookups)
 117:                 inventDimNew = InventDim::findOwnCondDispSiteLocSerial(inventDimOrig.configId,
 118:                     inventDimOrig.InventSizeId, inventDimOrig.InventColorId, inventDimOrig.InventSiteId,
 119:                     inventDimOrig.InventLocationId, _inventSerialId);
 120:  
 121:                 // Move the registration to the new part
 122:                 wmsOrderTransType.moveReservation(inventDimNew);
 123:             }
 124:         }
 125:         else
 126:         {
 127:             throw error("'Exception::Error' Unable to updatePickListLineSerial due to null wmsOrderTrans object. Transaction aborted.");
 128:         }
 129:     }
 130: }
 131:  
 132: // PickList Register this line
 133: private void registerPickListLine()
 134: {
 135:     container   pks;
 136:     Map         dict;
 137:     ;
 138:     if(wmsOrderTrans != null)
 139:     {
 140:         // Create a Map (key/value pair)
 141:         dict = new Map(Types::Int64, Types::Container);
 142:         // Create a container
 143:         pks = [wmsOrderTrans.orderId, wmsOrderTrans.recVersion];
 144:         // Load the map with the recid and container
 145:         dict.insert(wmsOrderTrans.RecId, pks);
 146:         // Call finishPickingLines
 147:         wmsOrderTransType.finishPickingLine('', wmsOrderTrans.inventDim(), EmplTable::userId2EmplId(curUserId()), TimeNow());
 148:     }
 149:     else
 150:     {
 151:         throw error("'Exception::Error' Unable to registerPickListLine due to null wmsOrderTrans object. Transaction aborted.");
 152:     }
 153: }
 154:  
 155: // Register the packing slip
 156: private void registerPackingSlipLine()
 157: {
 158:     ;
 159:     if(wmsOrderTrans != null)
 160:     {
 161:         // Register PackingSlip using a custom method we wrote (supplied below)
 162:         packingSlipId = SalesFormLetter::createPackingSlipWithDlvMode(wmsOrderTrans.inventTransRefId, dlvMode.Code);
 163:     }
 164:     else
 165:     {
 166:         throw error("'Exception::Error' Unable to registerPackingSlipLine due to null wmsOrderTrans object. Transaction aborted.");
 167:     }
 168: }
 169:  
 170: // Method to save the tracking numbers for the shipment
 171: public void saveTrackingNumbers(container _trackingNumbers, Date _shipDate)
 172: {
 173:     ShipCarrierPackage      shipPkgCarrier;
 174:     container               trackMetaData;
 175:     int                     pos;
 176:     ;
 177:     if(wmsOrderTrans != null)
 178:     {
 179:         pos = 1;
 180:         while(pos <= conlen(_trackingNumbers))
 181:         {
 182:             trackMetaData = conpeek(_trackingNumbers, pos);
 183:  
 184:             shipPkgCarrier.SalesId                  = wmsOrderTrans.inventTransRefId;
 185:             shipPkgCarrier.Weight                   = conpeek(trackMetaData, 2);
 186:             shipPkgCarrier.ShipDate                 = _shipDate;
 187:             shipPkgCarrier.PackingSlipId            = packingSlipId;
 188:             shipPkgCarrier.ShipCarrierTrackingNum   = conpeek(trackMetaData, 1);
 189:             shipPkgCarrier.CarrierId                = dlvMode.ShipCarrierId;
 190:             shipPkgCarrier.insert();
 191:             pos++;
 192:         }
 193:     }
 194:     else
 195:     {
 196:         throw error("'Exception::Error' Unable to saveTrackingNumbers due to null wmsOrderTrans object. Transaction aborted.");
 197:     }
 198: }
 199:  
 200: // Custom PacklingSlip registration
 201: public static PackingSlipId createPackingSlipWithDlvMode(SalesId _salesId, CustDlvModeId _dlvMode)
 202: {
 203:     // 06/12/2010: CCK
 204:     // Needed to create a new packing slip method that allowed changing of the delivery mode.
 205:     SalesFormLetter_PackingSlip packingSlip;
 206:     SalesTable                  localSalesTable;
 207:     DlvMode                     dlvMode;
 208:     ;
 209:     // Retrieve the dlvmode record
 210:     dlvMode = dlvMode::find(_dlvMode);
 211:     // Retrieve the sales record
 212:     localSalesTable = SalesTable::find(_salesId);
 213:     // Construct the SalesFormLeter using the Document Status Enum
 214:     // The base class knows to construct the SalesFormLetter_PackingSlip from this enum
 215:     packingSlip = SalesFormLetter::construct(DocumentStatus::PackingSlip);
 216:  
 217:     // Set a few override methods (this is only so we can override the Shipping Method set in the Sales Order)
 218:     // There are times when the Shipping Method is changed @ shipment and allows us to override the
 219:     // Shipping method set in the sales order. If you need more information contact me. You can remove
 220:     // this code for your use.
 221:     if(strUpr(localSalesTable.DlvMode) != strUpr(_dlvMode))
 222:     {
 223:         packingSlip.parmOverrideDlvMode(dlvMode.Code);
 224:         packingSlip.parmOverrideShipCarrier(dlvMode.ShipCarrierId);
 225:     }
 226:     // Call update passing the the salesTable
 227:     packingSlip.update(localSalesTable, SystemDateGet(), SalesUpdate::PickingList, AccountOrder::None, NoYes::No, NoYes::No);
 228:     return packingSlip.getPackingListId();
 229: }
Posted: Jun 22 2010, 08:35 by ckane | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Verizon HTC Droid Incredible

This is an update on my order and ship date.

Order Date: 05/20

Ship Date  : 06/04

Received   : 06/07


We are looking at a a 2 week delay in shipping.

Posted: Jun 07 2010, 07:48 by ckane | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under:
Goodbye AT&T and Apple. Hello Verizon and HTC Droid Incredible

So I finally gave up on AT&T and Apple and have moved on HTC/Google and Verizon. Why? Well, I’ve gone through 2 iPhones in 36 months and I'm NOT happy about it. I’m not hard on phones but my first iPhone had a battery go bad @ month 18 and I bought a 3G because I couldn’t wait a month for Apple to fix it not to mention MMS and tethering were supposed to be available on the 3GS. Now 18 months after that, the home button just quit working. That was just the last straw!

Below is a list of reasons why I had to give up on both companies:

  • AT&T – MMS support 6 months late
  • AT&T – Visual voicemail quit working when server msg stored reached 200
  • AT&T – No tethering until 18 months later AND they want to chage $20/mo
  • AT&T – elimination of unlimited data plan
  • AT&T - $350 to cancel any iPhone contact. PERIOD!
  • AT&T – Refuses to support Skype
  • AT&T – Refuses to support any video streaming not involving THEIR services
  • AT&T - Dropped calls - Especially when iPhone to iPhone
  • APPLE – Too many hardware deficiencies to list (Apple’s never been a hardware company)
  • APPLE – Brick the phone when you violate THEIR software agreement
  • APPLE – Horrible turn around time on faulty iPhone
  • APPLE – Can’t replace the battery and batter life SUCKS
  • APPLE – Lack of TRUE x64 support. Office plug-in fails with Office x64 and no support for it in the future but they offer a 64 bit iTunes. (Means no real x64 experience in their software department)
  • APPLE – Software platform requires “APPROVAL” – That’s not open source!
  • APPLE - Lack of flash with camera.
  • APPLE - Lack of Flash support (And Adobe and Flash are in bed together)
  • APPLE - Lack of Silverlight support (Don't ask - it's a developer thing)

Quite a list huh? Look. There are so many competing products out there and I find it rather strange that Apple can brick your phone even AFTER you paid for it. Does Apple brick your Mac if you install an OS other then Mac OSX? No.

Apple has always had a nasty habit of not playing well with others and being rather demanding. The iPhone will always have a place in history but it doesn’t take long before the competition catches up.

Never was a fan of Apple….they are innovators when it comes to UI but they fall short everywhere else.

Posted: Jun 07 2010, 07:38 by ckane | Comments (2) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: General
Microsoft Silverlight Client for Facebook available

 

image

Microsoft Silverlight 4 Beta Client for Facebook

The Microsoft Silverlight 4 Client for Facebook has been released as a developer preview sample. To use it you must have Silverlight 4 developer builds installed.

Posted: May 22 2010, 17:09 by ckane | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: Silverlight
Blog Changes

So I updated the blog to BlogEngine.NET version 1.6.1.0 and decided to do a Theme change. Hopefully this will work out just fine.

Posted: May 04 2010, 09:11 by ckane | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: General
(SOLVED) LINQ to SQL : SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM

This annoying error when calling SubmitChanges() from a LINQ to SQL DataContext can occur if you are using a default value for a DateCreated DateTime column which is NOT NULL, and you add a table to the LINQ to SQL designer.  For whatever reason, it doesn’t pick up that it has a default value, so you need to highlight the column and go to properties, and manually set the ‘Auto Generated Value’ property to ‘True.’

Thanks blogcoward

Posted: Apr 16 2010, 10:24 by ckane | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: LINQ