Layout Table Control like HTML table, tr and td tags






4.74/5 (18 votes)
Feb 29, 2004
3 min read

90218

1368
Table Control to polish your forms layout.
Introduction
Have you ever worked on ASP.NET and than moved back to Windows programming using Windows forms? Did you miss something?
Well I did! Why are there no controls like the HTML <table>, <tr> and <td> tags (and controls) to polish your layout?
Microsoft will introduce them with the next version of Windows forms. If you do not want to wait, you might try this control.
Using the code
I have created three controls that will help you layout your Windows Forms applications using a HTML <table>
like control without writing one line of code.
All you have to do is compile the TableControl project, add the TableControl.dll to your solution and add the TableControl
Component to your Visual Studio Toolbox using Add/Remove Items... in the context menu.
After that you can use the TableControl
just like any other Windows Forms control and drag it onto your form.
Add a couple of rows to the table and columns to the rows using the Collection Editor and you are all set. Drag any Windows Forms control to the columns and they will move just like HTML items added to a table.
To make your table useful, you have to specify how you want your rows and columns scaled. You have three choices: auto
, percent
, or pixel
.
Auto
will split the space available equally between the rows or columns - this is useful if you want to divide your form into a couple of sections.Percent
will give your row or column a defined percentage of the controls size - it allows to have smaller and wider rows or columns, that scale when resizing the form.Pixel
will give your row or column a fixed amount of pixels - which is useful for a row of buttons or a header that you want not to scale.
You can add rows, columns, set the type, width and height of the items added to the table.
The TableControl
does not allow to add anything but a row to the table using the designer. And a row does not allow anything to be added but a column.
Points of Interest
I found it very easy to build a control and implement Visual Studio Designer support for custom collections.
All you have to do is implement the IList
interface as I did for ColumnCollection
and RowCollection
. These Collections are used to keep references for all the rows (RowControl
) and columns (ColumnControl
) in my TableControl
.
Since there is already a collection that keeps all the controls in a list, I implemented something like a "virtual" IList
collection.
//
// A RowCollection is a proxy to the Controls collection inside
//
public class RowCollection : IList
{
private TableControl parentTable;
public RowCollection(TableControl parent)
{
this.parentTable = parent;
}
public bool IsReadOnly
{
get
{
return parentTable.Controls.IsReadOnly;
}
}
object IList.this[int index]
{
get
{
return this.parentTable.Controls[index];
}
set
{
throw new NotSupportedException("IList.this");
}
}
...
The RowCollection
IList
implementation always uses its parent's Controls
collection to retrieve a row.
To use this collection with the Visual Studio Designer, you have to implement a public
Indexer which allows you to access typed objects that are in the collection.
//
// This is the Indexer the designer is looking for...it will
// offer a collection editor for items of type RowControl
//
public RowControl this[int index]
{
get
{
return parentTable.Controls[index] as RowControl;
}
}
In my TableControl
, the types TableControl
, RowControl
and ColumnControl
are all derived from System.Windows.Forms.Panel
. This adds support for borders and background colors - getting closer to an HTML table.
To make the TableControl
easier to use in Visual Studio, I added public properties to the rows collection not only to the TableControl
but also to the RowControl
and the ColumnControl
. This is really no trick since the collections are "virtual" anyway:
//
// This is the Indexer the designer is looking for...it
// will offer a collection editor for items of type RowControl
//
public RowCollection Rows
{
get
{
if (this.Parent is TableControl)
return (this.Parent as TableControl).Rows;
throw new ArgumentException("Row Control is not placed in a table.");
}
}
This is really all you have to do to bring up the collection editor for the rows and columns from a table, row or column and have your own types inserted into your application's code:
To stop the designer from allowing other controls to be dragged directly into my table or my row, I added an override to my RowControl
and TableControl
implementation:
//
// Only allow a ColumnControl to be added
//
protected override void OnControlAdded(ControlEventArgs e)
{
if (e.Control is ColumnControl)
base.OnControlAdded (e);
else
throw new ArgumentException("You cannot add a " +
"Control directly to a row. Please insert a Column.");
}
Finally, I do not want to allow anybody to drag a row or column to a form:
//
// Do not add RowControl and ColumnControl to the Toolbox,
// only TableControl can be added
//
ToolboxItem(false)]
public class RowControl : System.Windows.Forms.Panel
{
...
[ToolboxItem(true)]
public class TableControl : System.Windows.Forms.Panel
{
...
That's all.
History
First release.