A brief introduction to TeeGrid.NET

Do please download the source code and/or the executable binary for this article.

TeeGrid.NET is a high-performance alternative to Visual Studio’s DataGridView which also offers more flexibility in data rendering. This article will show you, step-by-step, how to use TeeGrid.NET to connect to your data and some of the most important advantages it has over Visual Studio’s default grid.

The data we use for this example is an XML file which has been added into the Visual Studio project as a resource:

From this XML file we can create a DataSet instance from which we have access to one or other of its two DataTables:

DataSet GetDataSet()
{
    DataSet dataSet = new DataSet();
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(Resources.SampleData);
    dataSet.ReadXml(new XmlNodeReader(doc), XmlReadMode.ReadSchema);
    return dataSet;
}
 
DataTable GetTable()
{
    switch (DataSourceTable)
    {
        case DataSourceTable.Orders:
            return _dataSet.Tables[1];
        default:
            return _dataSet.Tables[0];
    }
}
DataSet GetDataSet()
{
	DataSet dataSet = new DataSet();
	XmlDocument doc = new XmlDocument();
	doc.LoadXml(Resources.SampleData);
	dataSet.ReadXml(new XmlNodeReader(doc), XmlReadMode.ReadSchema);
	return dataSet;
}

DataTable GetTable()
{
	switch (DataSourceTable)
	{
		case DataSourceTable.Orders:
			return _dataSet.Tables[1];
		default:
			return _dataSet.Tables[0];
	}
}

This table is then assigned to the BindingSource added at designtime, which is then assigned to the DataSource property of the TeeGrid in an identical manner by which it is assigned to the Visual Studio grid:

if (numRows > 0)
    bindingSource1.DataSource = _table.AsEnumerable().Take(numRows).ToList();
else
    bindingSource1.DataSource = _table;
 
tGrid1.DataSource = bindingSource1;
dataGridView1.DataSource = bindingSource1;
if (numRows > 0)
	bindingSource1.DataSource = _table.AsEnumerable().Take(numRows).ToList();
else
	bindingSource1.DataSource = _table;

tGrid1.DataSource = bindingSource1;
dataGridView1.DataSource = bindingSource1;

This gives us both grids assigned to the same BindingSource:

Now we can try testing the rendering performance of both grids while they are both connected to the same data using the same technique – this is the function of the FPS test, which here gives me this:

Results:

Test FPS
Both 15.01
DataGridView 14.32
TeeGrid 96.09

I think the difference is clear! TeeGrid’s data-rendering flexibility comes into play when it comes to representing LINQ queries performed on these data sources, one of which we’ve already seen in the code above – the ability of TeeGrid to easily represent a sub-set of DataRows taken from one of the DataTables:

note that the output of this LINQ is assigned to the BindingSource to which both grids are connected, but only TeeGrid is able to faithfully represent it. Now try the ‘Combination’ DataSource table:

Here the LINQ query is a little more complex, as we are performing a Join on the two tables:

DataTable customers = _dataSet.Tables[0];
DataTable orders = _dataSet.Tables[1];
 
List list = orders.AsEnumerable().Join(
    customers.AsEnumerable(),
    x => x.Field("CustomerID"),
    y => y.Field("CustomerID"),
    (x, y) => new OrderByCustomer {
        Order = new Order {
            OrderNo = x.Field("OrderID"),
            SaleDate = x.Field<DateTime?>("OrderDate"),
            UnitPrice = x.Field("Freight")
        },
        Customer = new Customer {
            CustNo = y.Field("CustomerID"),
            City = y.Field("City"),
            Company = y.Field("CompanyName")
        }
    }).DefaultIfEmpty().OrderBy(z => z.Customer.CustNo).ToList();
 
if (numRows > 0) list = list.Take(numRows).ToList();
 
bindingSource1.DataSource = null;
bindingSource1.DataSource = typeof(OrderByCustomer);
list.ForEach(x => bindingSource1.Add(x));
 
tGrid1.Data = new VirtualListData(list);
DataTable customers = _dataSet.Tables[0];
DataTable orders = _dataSet.Tables[1];

List list = orders.AsEnumerable().Join(
	customers.AsEnumerable(),
	x => x.Field("CustomerID"),
	y => y.Field("CustomerID"),
	(x, y) => new OrderByCustomer {
		Order = new Order {
			OrderNo = x.Field("OrderID"),
			SaleDate = x.Field<DateTime?>("OrderDate"),
			UnitPrice = x.Field("Freight")
		},
		Customer = new Customer {
			CustNo = y.Field("CustomerID"),
			City = y.Field("City"),
			Company = y.Field("CompanyName")
		}
	}).DefaultIfEmpty().OrderBy(z => z.Customer.CustNo).ToList();

if (numRows > 0) list = list.Take(numRows).ToList();

bindingSource1.DataSource = null;
bindingSource1.DataSource = typeof(OrderByCustomer);
list.ForEach(x => bindingSource1.Add(x));

tGrid1.Data = new VirtualListData(list);

Note again that TeeGrid is able to faithfully represent the output of this LINQ query, but this time the output is not being assigned to TeeGrid via the BindingSource but directly to TeeGrid’s Data property which takes derivatives of TeeGrid’s VirtualData class. Sorting of the SubColumns, for example the ‘UnitPrice’ column which is a logical child of the ‘Order’ column, can easily be performed by mouse-clicking on it.

So that’s it for now! Do please feel free to ask any questions in the comments below.

christopher

Developer at Steema Software

Leave a Reply

Your email address will not be published. Required fields are marked *