Использование True DBgrid при создании приложений для управления базами данных
на Visual Studio.Net (часть 2)
Введение во вторую часть
В
первой части статьи мы рассмотрели основные принципы использования True DBGrid и «облегченных» компонентов доступа к данным. Были рассмотрены
принципы связывания True
DBGrid с данными, а также форматирование
содержимого таблицы. Давайте двигаться дальше.
Фильтрация и сортировка
записей средствами True DBGrid
По
сравнению с предыдущими версиями True
DBGrid.NET получила
расширенные возможности фильтрации и сортировки записей.
Для
фильтрации записей Component
One снабдила True DBGrid
специальной панелью – FilterBar. Он появляется в верхней части таблицы, если
установить в true соответствующее свойство. Конечно же, это можно
сделать и программно. Я, например, добавил на форму кнопку, и в обработчике ее
нажатия ввел код:
C#
c1TrueDBGrid1.FilterBar=!c1TrueDBGrid1.FilterBar;
FilterBar имеет следующий вид:
Рис
1
Теперь
стоит в FilterBar начать вводить текст, как True DBGrid начнет фильтрацию записей в
соответствующей колонке по введенным символам:
Рис2
(Внимание!
По умолчанию фильтр чувствителен к регистру). Для того, чтобы сбросить фильтр,
необходимо его очистить.
Фильтрацию
можно производить по нескольким столбцам одновременно. В этом случае введенные
значения фильтра в разных столбцах будут связаны между собой логическим
соотношением «И».
Вот
так выглядит фильтрация в ее простейшем виде. Для того чтобы сделать более
сложный вариант, придется немного потрудиться. Давайте сделаем так, чтобы
значение фильтра можно было выбрать из комбобокса.
Хотя
True DBGrid позволяет встроить в ячейку и обычный комбобокс, Component One предоставляет для этого случая специальный контрол - True DBDropdown. Предположим, что в качестве фильтра мы будем
использовать фамилию (LastName) сотрудника. Помещаем на нашу форму True DBDropdown и еще один элемент C1ExpressTable, и связываем его с той же таблицей (еще один C1ExpressTable нужен для того, чтобы выпадающий список не зависел от фильтра).
Элемент True DBDropdown можно поместить в любом месте формы.
Рис
3
Теперь
связываем True DBDropdown с данными. Процедура связывания с данными True
DBDropdown ничем не отличается от связывания с данными True DBGrid. В качестве
источника данных применяем c1ExpressTable2. В отличие от простого комбобокса
True DBDropdown умеет отображать в выпадающей части несколько колонок. Нас же
интересует только поле LastName, поэтому в окне свойств открываем коллекцию
Columns, и удаляем все поля, за исключением LastName.
Далее
открываем редактор таблицы True DBGrid, переходим на вкладку Display Columns,
выбираем колонку LastName и устанавливаем
FilterButton=true
Button=false
Конечно
же, все можно сделать программно:
C#
c1TrueDBGrid1.Columns[1].DropDown=c1TrueDBDropdown1;
c1TrueDBGrid1.Splits[0].DisplayColumns[1].FilterButton=true;
c1TrueDBGrid1.Splits[0].DisplayColumns[1].Button=false;
VB.NET
Me.C1TrueDBGrid1.Columns(1).DropDown = Me.C1TrueDBDropdown1
Me.C1TrueDBGrid1.Splits(0).DisplayColumns(1).FilterButton
= True
Me.C1TrueDBGrid1.Splits(0).DisplayColumns(1).Button
= False
Запускаем
приложение. Если установить фокус в ячейку FilterBar над
колонкой LastName, появляется встроенный комбобокс. После выбора элемента
из комбобокса срабатывает фильтр.
Рис
4
Сортировка
записей осуществляется просто щелчком на заголовке колонки. Первый щелчок
включает сортировку выбранной колонки в возрастающем порядке. Повторный щелчок
переключает колонку в режим сортировки в обратном порядке. Одновременно может
быть включена сортировка только по одной колонке.
Принудительно
включить сортировку можно двумя способами:
- в
дизайнере выбрать колонку и установить соответствующее значение свойства SortDirection. Возможны три значения этого свойства:
-
None (по умолчанию);
-
Ascending;
-
Descending;
-
установить сортировку программно:
C#:
c1TrueDBGrid1.Columns[1].SortDirection=C1.Win.C1TrueDBGrid.SortDirEnum.Ascending;
Объединение ячеек True
DBGrid
Данная
опция уже знакома пользователям MS
FlexGrid. Теперь она доступна и в True DBGrid.
Перед
тем, как объединять ячейки необходимо уяснить, что объединяются СОСЕДНИЕ
ячейки, то есть, ваш набор записей должен быть отсортирован по тому полю,
ячейки которого вы собираетесь объединять.
Для
объединения ячеек следует в дизайнере установить в True свойство Merge выбранной
колонки (находится на вкладке Display
Columns)
Рис
5.
То
же самое программно:
C#:
c1TrueDBGrid1.Splits[0].DisplayColumns[1].Merge=true;
True DBGrid поддерживает только
режим объединения строк.
Расширенные
режимы отображения данных в True DBGrid
До
сих пор мы отображали данные в таблице в обычном порядке: поля следуют слева
направо, записи сверху вниз, каждая запись отображается в виде одной строки.
Кроме
этого True DBGrid умеет отображать данные еще в нескольких видах. За это
отвечает свойство DataView таблицы. Возможные варианты:
1.
Normal (значение по умолчанию) – обычный вид таблицы, что
собственно и было у нас до сих пор.
2.
Inverted – в этом режиме колонки и столбцы меняются местами:
Рис
6.
3.
Form - в этом режиме в таблице отображается только одна
запись в виде формы (аналогично просмотру записей в FoxPro)
Рис
7.
Перемещаться
по записям в этом режиме можно с помощью нижней полосы прокрутки.
4.
MultipleLine – в этом
режиме каждая запись отображается в несколько строк, причем True DBGrid
автоматически подгоняет ширину колонок. Нижняя полоса прокрутки в этом режиме
не отображается
Рис
8.
5.
GroupBy – в этом режиме
в верхней части таблицы отображается специальная панель:
Рис
9.
Если
на эту панель методом Drag & Drop
перетащить заголовок столбца (свойство AllowColMove должно быть установлено в True), произойдет группировка
записей по значению данного столбца:
Рис
10.
Вы
наверное уже заметили на приведенных картинках комбобокс, переключающий виды
таблицы. Вот код обработчика:
C#:
private void
comboBox1_SelectedIndexChanged(object sender, System.EventArgs
e)
{
switch(comboBox1.SelectedIndex)
{
case
0:
c1TrueDBGrid1.DataView=C1.Win.C1TrueDBGrid.DataViewEnum.Normal;
break;
case
1: c1TrueDBGrid1.DataView=C1.Win.C1TrueDBGrid.DataViewEnum.Inverted;
break;
case
2: c1TrueDBGrid1.DataView=C1.Win.C1TrueDBGrid.DataViewEnum.Form;
break;
case
3: c1TrueDBGrid1.DataView=C1.Win.C1TrueDBGrid.DataViewEnum.GroupBy;
break;
case
4: c1TrueDBGrid1.DataView=C1.Win.C1TrueDBGrid.DataViewEnum.MultipleLines;
break;
case 5:
break;
}
}
VB.Net
Private Sub
ComboBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As
System.EventArgs) Handles
ComboBox1.SelectedIndexChanged
Select Case ComboBox1.SelectedItem
Case
0
Me.C1TrueDBGrid1.DataView
= C1.Win.C1TrueDBGrid.DataViewEnum.Normal
Case
1
Me.C1TrueDBGrid1.DataView
= C1.Win.C1TrueDBGrid.DataViewEnum.Inverted
Case
2
Me.C1TrueDBGrid1.DataView
= C1.Win.C1TrueDBGrid.DataViewEnum.Form
Case
3
Me.C1TrueDBGrid1.DataView
= C1.Win.C1TrueDBGrid.DataViewEnum.GroupBy
Case
4
Me.C1TrueDBGrid1.DataView
= C1.Win.C1TrueDBGrid.DataViewEnum.MultipleLines
Case
5
End Select
End
Sub
Теперь
еще об одном режиме отображения – Hierarchical. В этом режиме подразумевается
использование источника данных, содержащего две или более связанные таблицы.
c1ExpressTable такой режим не поддерживает. Поэтому используем стандартные
компоненты доступа к данным .NET. Для этого необходимы компоненты oleDbDataAdapter (два), oleDbConnection
и dataSet.
Используем ту же базу данных Northwind. Первый oleDbDataAdapter подключаем к
таблице Orders, второй – Order Details. Далее создаем dataSet. Схема dataSet показана на Рис 11.
Рис
11.
Теперь
устанавливаем свойство DataSource
таблицы в dataSet1, а
свойство DataMember в Orders
и обновляем поля.
В
процедуре загрузки формы пишем следующий код:
C#:
oleDbDataAdapter1.Fill(this.dataSet1);
oleDbDataAdapter2.Fill(this.dataSet1);
c1TrueDBGrid1.DataView=C1.Win.C1TrueDBGrid.DataViewEnum.Hierarchical;
Приложение
можно запускать:
Рис
12.
В
данном режиме в таблице отображаются последовательно поля родительской и
дочерней таблиц, причем в исходном состоянии поля дочерней таблицы скрыты, а в
первой колонке отображается знак «+». Щелчок по этому знаку раскрывает поля
дочерней таблицы.
Использование
в True DBGrid несвязанных колонок.
Необходимость
в применении несвязанных колонок обычно возникает, если необходимо отобразить
некоторые данные, которых нет в базе данных. Возможно и использование True
DBGrid полностью в несвязанном режиме.
Для
создания несвязанной колонки в конструкторе форм достаточно создать новую
колонку, и не связывать ее ни с какими данными.
Доступ
к ячейкам несвязанной колонки осуществляется так же, как и к любым другим.
Такие ячейки доступны для редактирования, причем редактирование можно разрешить
или запретить. А вот заполнение таких ячеек данными и сохранение данных из
несвязанных ячеек полностью ложиться на плечи программиста.
Каждый
раз, когда True DBGrid прорисовывает ячейку несвязанной колонки, возникает
событие UnboundColumnFetch. Это событие можно перехватить и использовать для
обработки данных.
Давайте
в качестве примера возьмем таблицу OrderDetails из той же базы
данных Northwind. В этой таблице имеются поля UnitPrice – цена
позиции, Quantity – количество и Discount – скидка. Давайте отобразим в
несвязанном поле сумму заказа.
Добавляем
в таблицу несвязанное поле, даем ему заголовок Summa. Теперь
перехватываем событие UnboundColumnFetch:
C#:
private void
c1TrueDBGrid1_UnboundColumnFetch(object sender,
C1.Win.C1TrueDBGrid.UnboundColumnFetchEventArgs e)
{
C1.Data.C1DataTable
dtData=c1ExpressTable1.DataTable;
C1.Data.C1DataRow
drData=dtData.Rows[e.Row]; e.Value=(Convert.ToDecimal(drData[2])*Convert.ToInt32(drData[3])*(1-Convert.ToDecimal(drData[4]))).ToString("f2");
}
VB.NET
Private Sub
C1TrueDBGrid1_UnboundColumnFetch(ByVal sender As Object, ByVal e As
C1.Win.C1TrueDBGrid.UnboundColumnFetchEventArgs) Handles
C1TrueDBGrid1.UnboundColumnFetch
Dim
dtData As C1.Data.C1DataTable
Dim
drData As C1.Data.C1DataRow
dtData = C1ExpressTable1.DataTable
drData = dtData.Rows(e.Row)
e.Value =
(Convert.ToDecimal(drData(2)) * Convert.ToInt32(drData(3)) * (1 -
Convert.ToDecimal(drData(4)))).ToString("f2")
End Sub
Запускаем
приложение, и видим, что в несвязанном поле отображается сумма:
Рис
13.
Пользовательская
отрисовка ячеек в True DBGrid.
Раньше
мы с вами уже рассмотрели форматирование ячеек таблицы. Но когда стандартных
средств уже не хватает, True DBGrid предоставляет программисту возможность самому,
«вручную» произвести отрисовку ячеек. Для этого следует перехватить событие
OwnerDrawCell, и в его обработчик вставить соответствующий код.
Во-первых,
если мы собираемся «вручную» отрисовывать колонку, необходимо ее свойство OwnerDraw установить в true.
Во-вторых,
если мы собираемся использовать для отрисовки средства GDI+, необходимо
подключить соответствующие пространства имен:
C#:
using System.Drawing.Drawing2D;
using
System.Drawing.Text;
VB.NET:
Imports System.Drawing.Drawing2D
Imports System.Drawing.Text
Теперь
пишем код:
C#:
private void
c1TrueDBGrid1_OwnerDrawCell(object sender,
C1.Win.C1TrueDBGrid.OwnerDrawCellEventArgs e)
{
if(e.Col==0)//отрисовывать
мы будем 1-ю колонку
{
//получаем текущий обект графики
Graphics
g=e.Graphics;
//получаем прямоугольник, соответствующий текущей ячейке
Rectangle
rt=new
Rectangle(e.CellRect.X,e.CellRect.Y,e.CellRect.Width,e.CellRect.Height);
//подготавливаем градиентную кисть
LinearGradientBrush
brGrad=new LinearGradientBrush(rt,Color.Red,Color.Blue,0,true);
//заполняем прямоугольник
градиентной заливкой
g.FillRectangle(brGrad,rt);
//подготавливаем белую кисть для вывода текста
SolidBrush brWhite=new SolidBrush(Color.White);
//получаем
строку из текущей ячейки
C1.Win.C1TrueDBGrid.C1DisplayColumn
dCol=c1TrueDBGrid1.Splits[0].DisplayColumns[e.Col];
//подготавливаем параметры
форматирования строки
StringFormat
stf=new StringFormat();
stf.Alignment=StringAlignment.Center;
//выводим
строку
e.Graphics.DrawString(dCol.DataColumn.CellText(e.Row),dCol.Style.Font,brWhite,rt,stf);
//даем знать, что событие
перехвачено
e.Handled=true;
//освобождаем ресурсы
brGrad.Dispose();
brWhite.Dispose();
}
}
VB.NET:
Private Sub
C1TrueDBGrid1_OwnerDrawCell(ByVal sender As Object, ByVal e As
C1.Win.C1TrueDBGrid.OwnerDrawCellEventArgs) Handles
C1TrueDBGrid1.OwnerDrawCell
'в VB.NET объектные переменные объявляем отдельно
Dim g As
Graphics
Dim rt
As RectangleF
Dim
brGrad As LinearGradientBrush
Dim
brWhite As SolidBrush
Dim
dCol As C1.Win.C1TrueDBGrid.C1DisplayColumn
Dim
stf As StringFormat
If
e.Col = 0 Then 'отрисовывать мы будем 1-ю колонку
'получаем текущий обект графики
g = e.Graphics
'получаем прямоугольник, соответствующий текущей
ячейке
rt = New RectangleF(e.CellRect.X, e.CellRect.Y,
e.CellRect.Width, e.CellRect.Height)
'подготавливаем градиентную кисть
brGrad = New
LinearGradientBrush(rt, Color.Red, Color.Blue, 0, True)
'заполняем прямоугольник градиентной заливкой
g.FillRectangle(brGrad, rt)
'подготавливаем белую кисть для вывода текста
brWhite = New SolidBrush(Color.White)
'получаем строку из текущей ячейки
dCol =
C1TrueDBGrid1.Splits(0).DisplayColumns(e.Col)
'подготавливаем параметры форматирования строки
stf = New StringFormat
stf.Alignment
= StringAlignment.Center
'выводим строку
e.Graphics.DrawString(dCol.DataColumn.CellText(e.Row), dCol.Style.Font,
brWhite, rt, stf)
'даем знать, что событие перехвачено
e.Handled = True
'освобождаем ресурсы
brGrad.Dispose()
brWhite.Dispose()
End If
End Sub
Запускаем
приложение и смотрим:
Рис
14.
Другой
пример:
C#:
private void
c1TrueDBGrid1_OwnerDrawCell(object sender, C1.Win.C1TrueDBGrid.OwnerDrawCellEventArgs
e)
{
if(e.Col==0)
{
Graphics
g=e.Graphics;
Rectangle rt=new
Rectangle(e.CellRect.X,e.CellRect.Y,e.CellRect.Width,e.CellRect.Height);
SolidBrush brRed=new SolidBrush(Color.Red);
g.FillEllipse(brRed,rt);
SolidBrush brGreen=new SolidBrush(Color.Green);
C1.Win.C1TrueDBGrid.C1DisplayColumn
dCol=c1TrueDBGrid1.Splits[0].DisplayColumns[e.Col];
StringFormat stf=new StringFormat();
stf.Alignment=StringAlignment.Center;
e.Graphics.DrawString(dCol.DataColumn.CellText(e.Row),dCol.Style.Font,brGreen,rt,stf);
e.Handled=true;
brRed.Dispose();
brGreen.Dispose();
}
}
VB.NET
Private Sub
C1TrueDBGrid1_OwnerDrawCell(ByVal sender As Object, ByVal e As C1.Win.C1TrueDBGrid.OwnerDrawCellEventArgs)
Handles C1TrueDBGrid1.OwnerDrawCell
Dim g
As Graphics
Dim
rt As RectangleF
Dim
brRed As SolidBrush
Dim
brGreen As SolidBrush
Dim
dCol As C1.Win.C1TrueDBGrid.C1DisplayColumn
Dim
stf As StringFormat
If
e.Col = 0 Then
g = e.Graphics
rt = New
RectangleF(e.CellRect.X, e.CellRect.Y, e.CellRect.Width, e.CellRect.Height)
brRed = New
SolidBrush(Color.Red)
g.FillEllipse(brRed, rt)
brGreen = New SolidBrush(Color.Green)
dCol =
C1TrueDBGrid1.Splits(0).DisplayColumns(e.Col)
stf = New
StringFormat
stf.Alignment =
StringAlignment.Center
e.Graphics.DrawString(dCol.DataColumn.CellText(e.Row),
dCol.Style.Font, brGreen, rt, stf)
e.Handled = True
brRed.Dispose()
brGreen.Dispose()
End If
End Sub
Запускаем,
смотрим:
Рис
15.
Здесь
главное – понять принцип, а дальше – флаг вам в руки…
Встроенные
контролы в ячейках True DBGrid.
Мы
с вами подошли к одной из наиболее интересных возможностей True DBGrid. Но прежде я хочу сделать небольшое отступление.
Вы
видите, что возможности True DBGrid поистине безграничны. Однако, каждая из этих
возможностей, будучи реализованной, притормаживает программу. А стоит
реализовать 5-6 таких возможностей (проверено практикой), как скорость
прорисовки таблицы становится неприемлемо низкой. Поэтому я хочу призвать вас
придерживаться принципа «разумной достаточности».
Теперь
приступим к встраиванию контролов.
Простейшим
вариантом является встраивание в ячейку командной кнопки. Такая возможность
заложена в True DBGrid изначально. Для этого достаточно установить в True свойство
Button соответствующего столбца. Это можно сделать либо в
дизайнере, либо программно:
C#:
c1TrueDBGrid1.Splits[0].DisplayColumns[0].Button=true;
Теперь
при выборе ячейки в указанном столбце будет отображаться кнопка:
Рис
16.
В
таком режиме кнопка будет отображаться только в выбранной строке. Если же
установить в True свойство ButtonOlways, кнопки будут
отображаться во всех строках:
Рис
17.
Если
же в True установить свойство ButtonText, в
командную кнопку превращается вся ячейка:
Рис
18.
Однако
сама по себе такая кнопка еще ничего сделать не может. Здесь весь труд снова
ложится на плечи программиста. Необходимо перехватить событие ButtonClick.
Для
начала давайте встроим в ячейку комбобокс. И хотя можно встроить и стандартный
комбобокс, давайте сделаем его сами. Вспомните, что комбобокс состоит из двух
частей – текстового поля и простого списка. Так вот, в качестве текстового поля
используем ячейку, и подсоединим к ней listBox.
Начинаем
работу. Я использовал таблицу Customers
из той же базы данных Northwind. Как ее отобразить в True
DBGrid вы уже знаете. Установим Button=true для
поля CompanyName.
Разместим
на форме listBox (обычный, из Windows Forms).
Разместить его можно в любом месте формы. Теперь свяжем listBox данными.
Для этого нам понадобится еще один c1ExpressTable.
Коннектим его к той же таблице. Свойство DataSource listBox устанавливаем
c1ExpressTable2. Заполним listBox данными из поля CompanyName.
Теперь
начинаем писать код (далее код на C#)
listBox должен быть изначально
невидимым. Для этого в конструкторе формы записываем:
listBox1.Visible=false;
Обрабатываем
нажатие кнопки в ячейке:
private void
c1TrueDBGrid1_ButtonClick(object sender,
C1.Win.C1TrueDBGrid.ColEventArgs e)
{
listBox1.Left=c1TrueDBGrid1.Left+c1TrueDBGrid1.Splits[0].DisplayColumns[0].Width+c1TrueDBGrid1.RecordSelectorWidth;
listBox1.Top=c1TrueDBGrid1.Top+c1TrueDBGrid1.RowTop(c1TrueDBGrid1.Row)+c1TrueDBGrid1.RowHeight;
listBox1.Width=c1TrueDBGrid1.Splits[0].DisplayColumns[2].Width;
listBox1.Visible=true;
}
В
этом коде мы позиционируем listBox
и делаем его видимым.
Теперь
обрабатываем двойной щелчок в listBox:
private void
listBox1_DoubleClick(object sender,
System.EventArgs e)
{
c1TrueDBGrid1.Columns[1].Text=listBox1.Text;
listBox1.Visible=false;
}
И
наконец, если пользователь щелкнет за пределами listBox, его
необходимо спрятать:
private void
c1TrueDBGrid1_Click(object sender,
System.EventArgs e)
{
listBox1.Visible=false;
}
Запускам
приложение, и видим работающий, встроенный в ячейку комбобокс:
Рис
19.
Я
намеренно показал пример «самопального» контрола, чтобы показать все принципы
работы с ним. А так ComponentOne
поставляет специальный компонент C1TrueDBDropdown, работу с которым мы уже рассмотрели выше.
В
качестве второго примера рассмотрим встраивание в ячейку True DBGrid DateTimePicker. Здесь применим другой подход: при перемещении фокуса
на требуемую ячейку разместим на ее месте (поверх ячейки) DateTimePicker.
Итак,
берем DateTimePicker и «бросаем» его на форму. В конструкторе формы делаем
DateTimePicker невидимым.
При
загрузке формы сделаем высоту DateTimePicker равной высоте ячейки таблицы:
private void
Form1_Load(object sender, System.EventArgs e)
{
dateTimePicker1.Height=c1TrueDBGrid1.RowHeight;
}
Теперь обрабатываем перемещение фокуса по ячейкам:
private void
c1TrueDBGrid1_RowColChange(object sender,
C1.Win.C1TrueDBGrid.RowColChangeEventArgs e)
{
//получаем колонку таблицы
C1.Win.C1TrueDBGrid.C1DataColumn
col = c1TrueDBGrid1.Splits[0].DisplayColumns[c1TrueDBGrid1.Col].DataColumn;
if(col.DataField
== "BirthDate")//нас интересует колонка "BirthDate"
{
//определяем координаты ячейки
Rectangle rt =
c1TrueDBGrid1.Splits[0].GetCellBounds(c1TrueDBGrid1.Row, c1TrueDBGrid1.Col);
//пересчитываем координаты в экранные
rt =
c1TrueDBGrid1.RectangleToScreen(rt);
//позиционируем dateTimePicker1
dateTimePicker1.Location
= RectangleToClient(rt).Location;
//устанавливаем размеры dateTimePicker1
dateTimePicker1.Size
= rt.Size;
//устанавливаем значение
dateTimePicker1.Text
= col.CellText(c1TrueDBGrid1.Row);
//отображаем
dateTimePicker1.Visible
= true;
}
else
//если колонка не та. прячем dateTimePicker1
dateTimePicker1.Visible = false;
}
И
наконец, обрабатываем изменения в DateTimePicker:
private void dateTimePicker1_ValueChanged(object sender, System.EventArgs e)
{
C1.Win.C1TrueDBGrid.C1DataColumn
col = c1TrueDBGrid1.Splits[0].DisplayColumns[c1TrueDBGrid1.Col].DataColumn;
col.Text = dateTimePicker1.Text;
}
Вот
что у нас получилось:
Рис
20.
Пользуясь
указанными приемами в ячейку True
DBGrid можно встроить практически любой
контрол.
Заключение
ко второй части
Мы
с вами рассмотрели большинство возможностей True DBGrid. С
их помощью можно решить практически любую задачу.
Следующую
часть я хочу посвятить «профессиональным» средствам доступа к данным (С1.Data).
Дальше у нас останутся:
-
печать отчетов непосредственно средствами True DBGrid;
-
сохранение настроек True
DBGrid в файл на диске и восстановление
этих настроек;
-
FlexGrid.Net