πŸš€ go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.delphi.database.dotnet
1 messages
1 total messages Started by Brigitte Spatz Tue, 15 Aug 2006 15:39
combo box in data grid
#106
Author: 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.
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads