BYTEINSIGHT
GAPVelocity AI Studio helps you move from outdated tech stacks to the latest desktop, web, and cloud platforms—smarter, faster, and with less risk.
Choose a platform to see migration options:
Our comprehensive approach to application modernization, from assessment to production deployment.
Transformation Services
Not Sure Where to Start?
The first step is to identify and isolate the classes that will be upgraded with the Custom Maps functionality. The best way to ensure you are using the correct name is to open the Object Browser in the Visual Basic 6.0 IDE (View->Object Browser) and look for the library and class names. These names are important, since they are used to identify the type to transform.
For this example, the following screenshot shows the TrueDBGrid control Library and Class name.

Accordingly, the full name of this type will be TrueOleDBGrid80.TDBGrid. Once all the names are gathered, we should create a transformation table to identify the source and target constructs. For the test application they are as follows:
| VB6 original Name | .NET Fully qualified name |
| TrueOleDBGrid80.TDBGrid | C1.Win.C1TrueDBGrid.C1TrueDBGrid |
| XArrayDBObject.XarrayDB | System.Data.DataTable |
Note: The VB6 AI Migrator is able to upgrade the XArrayDB object to a custom helper class. This can be toggled from the Profile Manager window.
In addition to the types, it is necessary to include the members of the types that need to be transformed. This allows the creation of a realistic assessment of the amount of manual work required to transform one legacy control to its .NET counterpart. For the test application the type table can be extended as follows:
| VB6 original Name | .NET Fully qualified name |
| TrueOleDBGrid80.TDBGrid | C1.Win.C1TrueDBGrid.C1TrueDBGrid |
| .Array | No equivalent |
| .Rebind | No equivalent |
| XArrayDBObject.XarrayDB | System.Data.DataTable |
| .ReDim | No equivalent |
| .Value (Default indexed property) | No equivalent |
All the members used in the original code must be extracted from user code on the Visual Studio 6 IDE. This means that the types and members that can be transformed using Custom Maps must appear on the user modifiable code. By using the Find tool from Visual Studio we can easily look for variables of the types to replace and consequently look for references of their members. Once all the members are gathered, the next step is to compare those exposed members against the .NET counterpart (of the TrueDBGrid in this case). There is only one exposed member shared between the legacy and .NET versions of the TrueDBGrid control which is the .refresh method. This means that for this case, most of the functionality requires manual implementation.
It is necessary to fill the table with all the member references found on the user code. This means that the code included in the designer will not be considered. All the vendor-specific graphical properties that can be tweaked on the designer will not be upgraded since they are written on the upper part of the form that contains the control. These properties are not considered user code and will not be automatically upgraded. These properties, however, must be reviewed to ensure the target control will behave as closely as possible to the original, but they have to be manually added in the target code.
After the table contains the most commonly used members of the type to upgrade; the next step is to add the custom maps in the Custom Maps Editor.
The following screenshot shows how the Custom Maps editor should look like once all the information is entered:

Note that the exposed members that were not shared between the legacy and .NET version of the control where set to be eliminated from the code. This will comment out the line and add a EWI for easy tracking of these changes.
After all the parameters have been entered into the Custom Maps editor, we just need to enable the Custom Maps in the Profile Manager and we are ready to start the automated migration stage.
Once the code is migrated using the Custom Maps above, it is necessary to carefully review the output code of the migration tool to look for any detail that requires manual changes. To better understand the transformations done by the Custom Maps tool, the following paragraphs compare code segments from the original and resulting code.
The first comparison is between the declarations of the two types replaced using Custom Maps. The TrueDBGrid and the XArrayDB where successfully replaced by the target types, C1TrueDBGrid and the DataTable. The declaration of the TruDBGrid control is contained into the upper part of the of the Form1.frm file, which is reason why it is necessary to open it with a plain text editor such as Notepad. It is also possible to review all the properties mentioned in section ii.Identify the type members used throughout the code. The VB6 AI Migrator will extract the basic designer information (position, size) but the rest of the specific properties need to be manually entered in the .NET control using the designer. In this example, the most important properties that require manual intervention are the column names. Let’s take a look at the declaration code:
Begin TrueOleDBGrid80.TDBGrid TDBGrid1
Height = 2655
Left = 720
TabIndex = 0
Top = 840
Width = 7575
_ExtentX = 13361
_ExtentY = 4683
_LayoutType = 4
_RowHeight = -2147483647
_WasPersistedAsPixels= 0
Columns(0)._VlistStyle= 0
Columns(0)._MaxComboItems= 5
Columns(0).Caption= "Part Number"
Columns(0).DataField= ""
Columns(0)._PropDict= "_MaxComboItems,516,2;_VlistStyle,514,3"
Columns(1)._VlistStyle= 0
Columns(1)._MaxComboItems= 5
Columns(1).Caption= "Description"
(…)
End
public C1.Win.C1TrueDBGrid.C1TrueDBGrid TDBGrid1;
(…)
private void InitializeComponent()
{
(…)
this.TDBGrid1 = new C1.Win.C1TrueDBGrid.C1TrueDBGrid();
((System.ComponentModel.ISupportInitialize) this.TDBGrid1).BeginInit();
//
// TDBGrid1
//
this.TDBGrid1.Location = new System.Drawing.Point(48, 56);
this.TDBGrid1.Name = "TDBGrid1";
//Manual Change - This property is not needed
//this.TDBGrid1.OcxState = (System.Windows.Forms.AxHost.State) resources.GetObject("TDBGrid1.OcxState");
this.TDBGrid1.Size = new System.Drawing.Size(505, 177);
this.TDBGrid1.TabIndex = 0;
(…)
}
Note that the TDBGrid1.OcxState was included into the resulting code since this control was supposed to be used in .NET by means of a COM Runtime Callable Wrapper. This property is not exposed by the new native .NET component, so is no longer needed. The comment preceding that line was manually added to track manual changes easily. Review the upper part of the form1.frm file for the complete list of all the graphical properties of the TDBGrid1 control. The most important properties will be added to the resulting code in the next stages.
The next step is to review the declaration of the XArrayDB instance:
Dim XTrn As New XArrayDB
Private Sub Command1_Click()
(…)
XTrn.ReDim 1, LineNo, 1, 4
XTrn(LineNo, 1) = PartNum
XTrn(LineNo, 2) = Desc
XTrn(LineNo, 3) = LineNo + 2
XTrn(LineNo, 4) = LineNo + (LineNo / 5)
(…)
End Sub
private DataTable _XTrn = null;
DataTable XTrn
{
get
{
if (_XTrn == null)
{
_XTrn = new DataTable();
}
return _XTrn;
}
set
{
_XTrn = value;
}
}
private void Command1_Click( Object eventSender, EventArgs eventArgs)
{
(…)
//Manual Change - The XarrayDB object usage needs to be manually adapted
Object[] tempArray = new Object[4];
tempArray[0] = PartNum;
tempArray[1] = Desc;
tempArray[2] = LineNo + 2;
tempArray[3] = LineNo + (LineNo / 5d);
this.XTrn = (DataTable)this.TDBGrid1.DataSource;
this.XTrn.Rows.Add(tempArray);
//XTrn.ReDim(1, LineNo, 1, 4);
(…)
}
For the XArrayDB instance called “Xtrn” the VB6 AI Migrator applied a special transformation that ensures the members of form1 will be exposed in a safe way. The VB6 AI Migrator renamed the instance as “_Xtrn” and created a property to get and set this instance. This singleton pattern reproduces the behavior of the VB6 code accurately. The data type of this variable is not an ActiveX wrapper for the legacy XArrayDB object but a .NET ArrayList. This part of the code has no manual modifications whatsoever.
The next step is to populate the XArrayDB objects. This data type is used to store multidimensional arrays of information. In most scenarios it is used to store a collection of data rows which are at the same time collections of fields. In this case it is used as a bi dimensional array of data. The .NET resulting code was manually modified to store Arrays of object data types for each row of the Xtrn data container. This code now features a native .NET construction designed to store collections of data rows. To obtain the .NET code displayed in the previous example, it was necessary to:
So far, it has been necessary to comment out some unnecessary properties and re-factor the XArrayDB usage to work as a .NET DataTable. However, we configured the VB6 AI Migrator to delete 2 different members of the TrueDBGrid type.
//UPGRADE_NOTE: (8001) Element TrueOleDBGrid80.TDBGrid.Array was removed More Information: http://www.vbtonet.com/ewis/ewi8001.aspx
//TDBGrid1.Array = XTrn.GetOcx;
//UPGRADE_NOTE: (8001) Element TrueOleDBGrid80.TDBGrid.ReBind was removed More Information: http://www.vbtonet.com/ewis/ewi8001.aspx
//TDBGrid1.ReBind();
These members added information to the grid and made it visible. It is now necessary to manually add this functionality to the .NET code.
Once the changes are done to the type declarations, the next step is to make sure that their invocations and functionality is also preserved. The next section shows the last details required to achieve functional equivalence.
Graphical Properties of the TrueDBGrid control: on this example, the columns have particular names that need to be manually configured into the resulting code. To make sure that the code will be as .NET-like as possible the code to set those properties is added directly in the designer code, specifically in the “InitializeComponents” method. It is necessary to add the following code after the properties of the grid:
//Manual Change - Adding the Columns with their original names
this.TDBGrid1.Columns.Add(new C1.Win.C1TrueDBGrid.C1DataColumn("Part Number", typeof(string)));
this.TDBGrid1.Columns.Add(new C1.Win.C1TrueDBGrid.C1DataColumn("Description", typeof(string)));
this.TDBGrid1.Columns.Add(new C1.Win.C1TrueDBGrid.C1DataColumn("Quantity", typeof(string)));
this.TDBGrid1.Columns.Add(new C1.Win.C1TrueDBGrid.C1DataColumn("Price", typeof(string)));
//Manual Change - set the data biding to null
this.TDBGrid1.SetDataBinding();
All the rest of details that refers to the graphical appearance of the TrueDBGrid control can be manually set from this method or if desired, from the Visual Studio Graphical Designer.
Display the information into the TrueDBGrid control: The VB6 AI Migrator was configured to delete the appearances of 2 members of the TrueDBGrid control. These members used to set the internal bi dimensional array that stores the rows of the grid and the method that updates the graphical representation of the grid against the stored data.
In order to make this functionality available it is necessary to add two additional lines of code after the temporary Array of object data types is created.
this.XTrn = (DataTable)this.TDBGrid1.DataSource;
this.XTrn.Rows.Add(tempArray);
The first line assigns the Xtrn DataTable instance as a reference to the current DataSource of the .NET TrueDBGrid instance. This is necessary to ensure the Xtrn property will match the internal data representation of the TDBGrid1 instance in the number of columns, their data types and many other parameters.
The second line adds a new row to the Xtrn DataTable. Since the previous line assigned the Xtrn property to the DataSource member of the TDBGrid1 instance, this will add a new row of data into the graphical control as well.
The final product is the .NET version of the original application using the .NET counterparts of the original controls, plus some important transformations that improves the code appearance.
Continue reading: