Tag Archives: DataTable

Serialized Subtypes of DataTable in VB.NET

I ran across a painful problem late last week with DataTables in VB.NET.  It started when I realised that my derived class off a DataTable wasn’t serializing the instance members specific to that  derived class. I dug around and discovered that things get worse.  Not only have others discovered my pain, but under VB.NET I’m not allowed to step in and supply alternative serialization code for the subtype myself.  The proposed solution?  Work around the issue with your own serialization code  in C#, then put a VB.NET wrapper around the workaround to get access to it.  Though our reasons differ slightly, my supervisor and I agree that throwing a microscopic piece of C# into an entirely VB.NET application just isn’t going to happen.

Yet again, I am underwhelmed by the “second-class-citizen” approach Microsoft seems to have with respect to VB.NET.  First, there was that little fiasco where key basic refactoring tools are offered in the vanilla Visual Studio for C#, but not  VB.NET (yes, yes, I’m quite aware of the addons. Why they are necessary for VB.NET but not C# is what’s getting my goat).  Secondly, there’s that craziness where reflection doesn’t quite work the same under C# vs VB.NET (oh the fun times on forums peeps had on that one). And now, this…  I’m wondering what’s next in the hit-parade of  C# > VB.NET shennanigans that I’ll trip over.

It’s a bit of a crying shame really… I cut my teeth on a succession of languages based on C.  I’ve been playing in VB.NET long enough now, that I think finally grok “syntactic sugar causes cancer of the semicolon“.

So, what did I do?  First I pulled out NUnit and confirmed  for myself that I really was dealing with a situation where base DataTable state would serialize, that new derived class members won’t, and that I can’t do my own serialization for the derived class.

I then thought very hard about options.  The derived class provides strongly typed properties when accessing rows, and has kept complexity in my recursive reflection parser in the “understandable by humans” zone, so the derived class needs to stay.

Finally, I turned the the new members in the sub-class, and considered their lifecycle.  They’re essentially static context that the DataTable needs when  when I parse VB.NET structures into the DataTable. Once they’re in the DataTable, they’re basically redundant.  I finally sorted out something that I will call “tolerably sh*tty” when the supervisor asks:

Parameters Class Diagram

Initially, the “context” was being passed into the ParameterTable constructor. This context is  the new member state that serialization of DataTable refused to touch.

I’ve decided on an approach where I  added an interface that explicitly ties down exactly what constitutes this static context, and have both the ParameterTable and its container class implement it.  The interface allows me to ensure that I avoid a circular dependency where the ParameterTable explicitly knows its container, and it forces me to handle the static context in the same way in both classes.  In ParameterTable, if it finds it has context supplied externally, that will be used (necessary for the reflection parser). Otherwise, once the table is fully parsed, it can derive the information it needs from its own internal state.

I’m not wedded to this as a final solution, but it works and I hate it less than a VB.NET wrapper around C# code that I should have been able to do all in the one language.

Understanding GridDataBoundGrid

I’ve recently been replacing grid controls within the GUI of the simulation system we’ve been writing.  The current task is to retire older grids for Syncfusion’s GridDataBoundGrid. The key reason for it is that we can bind a DataTable to the grid as the data source, and sidestep having to manually write reams of  binding code by hand through to the DataTable. Below are notes that I think I’d like to have access to once I’ve forgotten what I did to get it all working.

The DataTable isn’t tightly-coupled to an underlying database table (we use it more for in-memory LINQ queries), so we’re binding the DataTable to the its GridDataBoundGrid dynamically (not via Visual Studio’s designer). Doing this, I soon learned that getting at the columns of the grid proved challenging. I needed to use the grid’s InternalColumns, not its GridBoundColumns. The key insight I missed when pouring through their usage manual was the following quote from Syncfusion support staff:

If you have not explicitly added columns to the GridBoundColumns collection (either through the designer or through code), then the GridBoundColumns (and also grid.GridBoundColumns) will be empty even after setting the grid.DataSource property. In this case, binder.InternalColumns will automatically be populated with the columns from the DataSource at the time the grid.DataSource property is set.

With that behind me, I got by mostly with FAQ entries on typical things people want to do with the grid.  I ran into another issue where I’d occasionally have to iterate through rows and/or columns to pull off certain pre-rendering hyjinks.  Unhelpfully, the maximum row index number is given via the call grid.GridCellsRange.Bottom. The maximun column index number is given via the call grid.GridCellsRange.Right.

I’d inherited a new sub-class off GridDataBoundGrid to keep grid behaviour reusable across screens. The extra (under-the-hood) properties I’d added began causing me grief once I dropped the grid into a form via the VS designer. The designer would attempt to automatically generate supporting code for the properties, which failed with a dialog stating  “Code generation for property ‘SomeProperty’ failed”. After some digging, I discovered that I could influence the designer on what it should do with my non-GUI properties via the DesignerSerializationVisibility attribute. Though I’d set the attribute correctly, the change wasn’t taking in the GUI.  I eventually realised that the toolbox was looking at the assembly containing the my new grid control. I’d need to rebuild that assembly explicitly to allow the toolbox to pick up a “latest” DLL containing the grid control.

Finally, the most challenging screen I’ve cut across involved 7 separate tabs, each using a grid that showed a “slice” of a 7000-odd row DataTable.  The fist attempt at having a separate grid per tab proved disastrous in terms of GUI initialisation speed, stretching into the minutes.  I rewrote it using a sleight-of-hand trick so that there was only one grid. Tab control event-handlers then “yank” the grid to the newly selected tab, and supply a filter over the DataTable that mapped to the given tab.  Table filtering was achieved using the RowFilter property of the DataTable’s DefaultView.  Because I’m filtering on the actual DataTable, this trick only works if there is only a single grid visible on the screen that has the given DataTable bound as its data source.

Phew! Desperately-seeking-chocolate!