πŸš€ go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.delphi.database.dotnet
Article #106

combo box in data grid

#106
From: Brigitte Spatz
Date: Tue, 15 Aug 2006 15:39
235 lines
8457 bytes
I have adapted the C# code from  
http://msdn.microsoft.com/msdnmag/issues/03/08/DataGrids/default.aspx for  
a data grid combo box column and added it to my data grid. I don’t get an  
error but the column is simply not displayed (but if I query  
VisibleColumnCount I get 7, which means it *should* be there, the row  
height is also visibly larger). Can anybody spot what I might be  
missing/doing wrong? TIA.

// init
   ts := DataGridTableStyle.Create;
   dc1 := DataGridTextBoxColumn.Create;
   dc2 := DataGridBoolColumn.Create;
   dc3 := DataGridTextBoxColumn.Create;
   dc4 := DataGridTextBoxColumn.Create;
   dc5 := DataGridTextBoxColumn.Create;
   dc6 := DataGridTextBoxColumn.Create;
   dc7 := DataGridComboBoxColumn.Create;
   ts.MappingName := 'ODM';
   ts.AlternatingBackColor := color.WhiteSmoke;
// column 1 – ordinary text box:
   dc1.MappingName := 'fld_odmID';
   dc1.HeaderText := 'ID';
   dc1.Alignment := HorizontalAlignment.left;
   dc1.NullText := '';
   dc1.Width := 45;
<snip – columns 2 – 6 are all text boxes>
// column 7 – the combo box:
   SetLookupBinding(dc7.Combobx, 'fld_LastName', 'fld_ContactID',
     ds.Tables['contact']); //see procedure below
   dc7.HeaderText := 'Ansprechpartner';
   dc7.Alignment := horizontalalignment.Left;
   dc7.NullText := '';
   dc7.Width := 150;

   ts.PreferredRowHeight := dc7.Combobx.Height + 1;
   ts.GridColumnStyles.Add(dc1);
   ts.GridColumnStyles.Add(dc3);
   ts.GridColumnStyles.Add(dc4);
   ts.GridColumnStyles.Add(dc5);
   ts.GridColumnStyles.Add(dc2);
   ts.GridColumnStyles.Add(dc6);
   ts.GridColumnStyles.add(dc7);

   datagrid1.TableStyles.Add(ts);

procedure SetLookupBinding(combobx: System.Windows.Forms.Combobox;
   DisplayColumn, BoundColumn: string; dt: DataTable);
begin
   with combobx do
   begin
     DisplayMember := DisplayColumn;
     ValueMember := BoundColumn;
     DataSource := dt;
   end;
end;

and the new class in a separate unit:

unit DataGridComboBoxColumnU;

interface

uses
   System.Windows.Forms, System.Drawing, System.Data;

type
   DataGridComboBoxColumn =  
class(System.Windows.Forms.DataGridTextBoxColumn)
   private
     { Private-Deklarationen }
     cm: CurrencyManager;
     intCurrentRow: Integer;
     cbb: Combobox; // Hosted combobox control
     procedure comboBox_Leave(sender: System.Object; e: EventArgs );
     procedure DataGrid_Scroll(sender: System.Object; e: EventArgs);
   protected
     procedure Edit(source: System.Windows.Forms.CurrencyManager;
       rowNum: Integer; bounds: System.Drawing.Rectangle; readOnly: Boolean;
       instantText: string; cellIsVisible: Boolean); override;
     function GetColumnValueAtRow(source:  
System.Windows.Forms.CurrencyManager;
       rowNum: Integer): System.Object; override;
     procedure SetColumnValueAtRow(source:  
System.Windows.Forms.CurrencyManager;
       rowNum: Integer; value: System.Object); override;
   public
     constructor Create;
     function Combobx: Combobox;
   end;

implementation

constructor DataGridComboBoxColumn.Create;
{Constructor - create combobox, register selection change event handler,
register lose focus event handler}
begin
   inherited Create;

   // Create combobox and force DropDownList style:
   cbb := Combobox.Create;
   cbb.DropDownStyle := ComboBoxStyle.DropDownList;

   // Add event handler for notification when combobox loses focus:
   Include(Self.cbb.Leave, Self.comboBox_Leave);
end;

function DataGridComboBoxColumn.Combobx: Combobox;
begin
   Result := cbb;
end;

procedure DataGridComboBoxColumn.comboBox_Leave(sender: System.Object; e:  
EventArgs );
{On combobox losing focus, set the column value, hide the combobox,
and unregister scroll event handler}
var
   str: string;
   rowView: DataRowView;
begin
   rowView := DataRowView(cbb.SelectedItem);
   str := string(rowView.Row[cbb.DisplayMember]);

   SetColumnValueAtRow(cm, intCurrentRow, str);
   Invalidate;

   cbb.Hide;
   Exclude(DataGridTableStyle.DataGrid.Scroll, DataGrid_Scroll);
end;

procedure DataGridComboBoxColumn.Edit(source:  
System.Windows.Forms.CurrencyManager;
   rowNum: Integer; bounds: System.Drawing.Rectangle; readOnly: Boolean;
   instantText: string; cellIsVisible: Boolean);
// On edit, add scroll event handler, and display combobox
var rect: Rectangle;
begin
   inherited Edit(source, rowNum, bounds, readOnly, instantText,
     cellIsVisible);

   if (not readOnly and cellIsVisible) then
   begin
     // Save current row in the DataGrid and currency manager
     // associated with the data source for the DataGrid
     intCurrentRow := rowNum;
     cm := source;

     // Add event handler for DataGrid scroll notification
     include(DataGridTableStyle.DataGrid.Scroll, DataGrid_Scroll);

     // Site the combobox control within the current cell
     cbb.Parent := TextBox.Parent;
     rect := DataGridTableStyle.DataGrid.GetCurrentCellBounds;
     cbb.Location := rect.Location;
     cbb.Size := Size.Create(TextBox.Size.Width, cbb.Size.Height);

     // Set combobox selection to given text
     cbb.SelectedIndex := cbb.FindStringExact(TextBox.Text);

     // Make the combobox visible and place on top textbox control
     cbb.Show;
     cbb.BringToFront;
     cbb.Focus;
   end;
end;

function DataGridComboBoxColumn.GetColumnValueAtRow(
   source: System.Windows.Forms.CurrencyManager; rowNum: Integer):  
System.Object;
{Given a row, get the value member associated with a row.  Use the
value member to find the associated display member by iterating
over bound data source}
var
   obj: System.&Object;
   dv: DataView;
   i: Integer;
begin
   // Given a row number in the DataGrid, get the display member
   obj := inherited GetColumnValueAtRow(source, rowNum);

   // Iterate through the data source bound to the ColumnComboBox
   cm :=  
CurrencyManager(DataGridTableStyle.DataGrid.BindingContext[cbb.DataSource]);
   // Assumes the associated DataGrid is bound to a DataView or
   // DataTable
   dv := DataView(cm.List);

   for i := 0 to dv.Count - 1 do
     if (obj.Equals(dv[i][cbb.ValueMember])) then
       break;
   // If set item was found return corresponding value,
   // otherwise return DbNull.Value
   if (i < dv.Count) then
     Result := dv[i][cbb.DisplayMember];
   Result := DBNull.Value;
end;

procedure DataGridComboBoxColumn.SetColumnValueAtRow(
   source: System.Windows.Forms.CurrencyManager; rowNum: Integer;
   value: System.Object);
{Given a row and a display member, iterate over bound data source to
find the associated value member.  Set this value member.}
var
   s: System.&Object;
   dv: DataView;
   i: Integer;
begin
   s := value;

   // Iterate through the data source bound to the ColumnComboBox:
   cm := CurrencyManager(
     DataGridTableStyle.DataGrid.BindingContext[cbb.DataSource]);
   // Assumes the associated DataGrid is bound to a DataView or
   // DataTable
   dv := DataView(cm.List);

   for i := 0 to dv.Count - 1do
     if (s.Equals(dv[i][cbb.DisplayMember])) then
       break;

   if i < dv.Count then
     s := dv[i][cbb.ValueMember]
   else
     s := DBNull.Value;

   inherited SetColumnValueAtRow(source, rowNum, s);
end;

procedure DataGridComboBoxColumn.DataGrid_Scroll(sender: System.Object; e:  
EventArgs);
// On DataGrid scroll, hide the combobox
begin
   cbb.Hide;
end;

end.
Technical Details
Message-ID: <op.teb0grt8i0jcwv@acer.mshome.net>
Path: arc1-ca.pugleaf.net!g2news2.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Thread: 1effe6,6e8c1db9518f8398,start
X-Google-Attributes: gid1effe6,public
X-Google-Language: ENGLISH,UTF8
Subject: combo box in data grid
From: "Brigitte Spatz" <brigitte.NOSPAMspatz@svenmahn.de>
Content-Type: text/plain; format=flowed; delsp=yes; charset=utf-8
MIME-Version: 1.0
Newsgroups: borland.public.delphi.database.dotnet
Content-Transfer-Encoding: 8bit
Date: Tue, 15 Aug 2006 17:39:53 +0200
Message-ID: <op.teb0grt8i0jcwv@acer.mshome.net>
User-Agent: Opera Mail/9.00 (Win32)
X-Antivirus: avast! (VPS 0633-1, 15/08/2006), Outbound message
X-Antivirus-Status: Clean
NNTP-Posting-Host: 217.189.155.8
X-Trace: newsgroups.borland.com 1155656403 217.189.155.8 (15 Aug 2006 08:40:03 -0700)
Lines: 236
Path: arc1-ca.pugleaf.net!g2news2.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail