Working with IOrder collections

Discussions related to custom development with Select.
Post Reply
ckootg
Posts: 122
Joined: Fri Jan 06, 2012 6:10 pm

Working with IOrder collections

Post by ckootg »

Are there any tips on working with IOrder collections?

As to specifics, eventually I'll need to loop through collections, find an item based on criteria (ie., LINQ), and bind them to a grid.

For looping, the easiest way I've found is to convert the collection into a dynamic variable, like so...

Code: Select all

dynamic contacts = IOrder["Contacts"];
foreach(dynamic contact in contacts) {}
Is there a better way of doing this?

As for the rest, I'm still looking.

Any tips would be appreciated.
John Morris
Posts: 411
Joined: Thu Sep 11, 2008 11:35 am
Location: Raleigh, NC, USA
Contact:

Re: Working with IOrder collections

Post by John Morris »

I thought you'd never ask! :)

To be accurate, we are really talking about collections of IOrderItems, not IOrders. Here are a few important items that come to mind.
  1. The use of dynamic is perfectly acceptable in this scenario.
  2. Collections in the order model are either IList or IDictionary based. Most of them are IList. In fact, the only IDictionary one that I know of, is the Lines collection under the HUD. In the field code browser, these will show as Collection or KeyedCollection types.
  3. All of our order items and collections have support for databinding. You can directly bind any of the objects or collections to a typical .NET control and expect the behavior to work correctly. This is how SoftPro has built all of our SnapSections. We mostly used basic databinding.
  4. If you want to filter a collection, you'll need to do that yourself and create a BindingSource to hold the items. That BindingSource can then be setup as the data source for the grid.
  5. Due to the lack of strong typing on the IOrder/IOrderItem interfaces, your ability to use LINQ on those interfaces will be limited. However, this should not present a performance issue. Just filter the list manually, i.e. foreach loops and such.
John Morris
Sr. Software Architect
SoftPro
ckootg
Posts: 122
Joined: Fri Jan 06, 2012 6:10 pm

Re: Working with IOrder collections

Post by ckootg »

Thanks for the tips. Really helpful!

More questions, though. :mrgreen:

When accessing a field more than one level down, I'm not able to with the indexer. For example, I can't access Address1 of an Address with contact["Address.Address1"] -- it says key not found. The only way would be to convert it to a dynamic. This doesn't work when I need to bind to a grid, though. Examples, please!

Also, I want to confirm I'm creating new collection items correctly. I'm using the CreateNew() method to create a new item and attaching it to the collection with Add(), which I found through the VS debugger. I also noticed a EndNew() method. What does that do?

Code: Select all

IOrderItem property;
IOrderItem taxMap = property.Order.CreateNew("TaxMap");
((dynamic)property).TaxMaps.Add(taxMap);
John Morris
Posts: 411
Joined: Thu Sep 11, 2008 11:35 am
Location: Raleigh, NC, USA
Contact:

Re: Working with IOrder collections

Post by John Morris »

The built in .NET data grid view does NOT support nested binding (Address.Address1). I believe it works with simple databinding, but not complex databinding. We had to work around this limitation too. It isn't related to our product. It is a known limitation of the .NET framework controls in WinForms.

The easiest way to get nested values is to use the dynamic keyword, like so:

Code: Select all

dynamic order = GetAnOrder();
var adr = (string)order.Properties[0].Address.Address1
An alternative way is to use our Query extension method, located in SoftPro.ClientModel. It works like a XPath statement against objects, like so:

Code: Select all

object oder = GetAnOrder();
var adr = order.Query("Properties[0]/Address/Address1").Cast<String>().Single();
And finally, you can always do it the old fashion way, like so:

Code: Select all

IOrder order = GetAnOrder();
IList properties = order["Properties"];
IOrderItem property = (IOrderItem)properties[0];
IOrderItem address = property["Address"];
string adr = (string)address["Address1"];
You are following the correct steps to add an item to the collection. You need to create a new instance (via CreateNew) and then add it the model, using Add method (in the case of a collection) or property assignment (in the case in a property).

The EndNew function is related to the .NET data binding interfaces and shouldn't be used by your code. It is used by the .NET framework.
John Morris
Sr. Software Architect
SoftPro
John Morris
Posts: 411
Joined: Thu Sep 11, 2008 11:35 am
Location: Raleigh, NC, USA
Contact:

Re: Working with IOrder collections

Post by John Morris »

Take a look at this link: http://code.google.com/p/object-binding-source/

It should help shed light on the nested binding issue with grids.
John Morris
Sr. Software Architect
SoftPro
John Morris
Posts: 411
Joined: Thu Sep 11, 2008 11:35 am
Location: Raleigh, NC, USA
Contact:

Re: Working with IOrder collections

Post by John Morris »

For the sake of clarity, this is an example of how to add a property...

Code: Select all

IOrder order = GetAnOrder();
IOrderItem prop = order.CreateNew("Property");
IList props = (IList)order["Properties"];
props.Add(prop);
John Morris
Sr. Software Architect
SoftPro
Post Reply