<$BlogRSDUrl$>

Saturday, June 11, 2005

Showing a true read-only DataGrid 

I had an interesting situation the other day where I wanted to use a WinForms DataGrid to display a read-only list of some ECO classes. I soon discovered that there is no easy way to support having a DataGrid where the entire row is selected when a record is clicked. Even though the DataGrid is read-only, an individual column can still get focus, with the caret painted and the contents highlighted.

Normally to get around this problem I would revert to using a ListView, where getting this behaviour is easy. But as the DataGrid was being used in an ECO WinForms application, I wanted to still use it so I could take advantage of the EcoFormExtender functionality offered when doing so. This includes being able to add, edit and delete ECO objects without writing a single line of code.

After a bit of judicial Googling, I found that I should be able to get the behaviour I wanted by creating a DataGridTextBoxColumn descendant and overriding its Edit method. Below is the code for this :-

procedure TDataGridUnselectableCellColumn.Edit(ASource: CurrencyManager;
ARowNumber: Integer; ABounds: Rectangle; AReadOnly: Boolean; AText: string;
ACellIsVisible: Boolean);
begin
if (FSelectedRow > -1) and (FSelectedRow < ASource.List.Count) then
DataGridTableStyle.DataGrid.UnSelect(FSelectedRow);
FSelectedRow := ARowNumber;
DataGridTableStyle.DataGrid.Select(FSelectedRow);
end;


This is all well and good, but I don't have design-time support for this TDataGridUnselectableCellColumn class, and I don't really want to stuff around too much to see if it is feasible to create a DataGrid descendant just so I can get it. To get around this problem, I created a base form containing a DataGrid which calls the below method on the WinForm.Load event :-

procedure TDataGridForm.InitializeGridColumns;
var
lTableStyle: DataGridTableStyle;
lSourceColumn: DataGridColumnStyle;
lDestColumn: TDataGridUnselectableCellColumn;
begin
lTableStyle := DataGridTableStyle.Create;
if dgMain.TableStyles.Count = 1 then
begin
for lSourceColumn in dgMain.TableStyles[0].GridColumnStyles do
begin
lDestColumn := TDataGridUnselectableCellColumn.Create;
lDestColumn.Alignment := lSourceColumn.Alignment;
lDestColumn.HeaderText := lSourceColumn.HeaderText;
lDestColumn.NullText := lSourceColumn.NullText;
lDestColumn.PropertyDescriptor := lSourceColumn.PropertyDescriptor;
lDestColumn.MappingName := lSourceColumn.MappingName;
lDestColumn.Width := lSourceColumn.Width;
lTableStyle.GridColumnStyles.Add(lDestColumn);
end;
dgMain.TableStyles.Clear;
dgMain.TableStyles.Add(lTableStyle);
end;
end;


So I now have an easy way to have a read-only display of a list of my ECO objects, simply by descending from this TDataGridForm and configuring the DataGrid.TableStyles property to contain the column mappings for the class attributes I wish to display. Not the most elegant solution for sure, but one I can live with for now.

Comments: Post a Comment

This page is powered by Blogger. Isn't yours?