delphitdbgrid

Set some cells in TDbGrid to editable


I want only some cells editable in a TDBGrid. In a given column, some but not all cells will be editable, so I can't just set Column.ReadOnly for the entire column and then leave it that way.

What events are best to use so I can get control when a cell is entered. I might use TDbGrid.ColumnEnter to catch horizontal movement and TDataSet.AfterScroll for vertical movement in the grid. Or I could perhaps use TDBGrid.DrawColumnCell (which I'm already using to change the color of some cells...)

And I'm also having trouble figuring out the best way change the read-only status of a cell. I could set the underlying TTable.Field.ReadOnly, or TDbGrid.Columns[].ReadOnly.

I could experiment with all of the above, but then I'm depending on my testing to determine how the grid is implemented, and might overlook some situation. I'd prefer to know if the VCL provides a way to manage this need, if there are caveats, etc.

Related: ReadOnly TDBGrid/TwwDBGrid Cell in Delphi?, but doesn't handle scrolling via the keyboard.


Solution

  • You can override the CanEditModify function and add your wished condition. This can be done by creating a new compoent with adding a new Event or just by an interposerclass.

    unit Unit6;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, DB, ADODB, Grids, DBGrids;
    
    type
      TDBGrid=Class(DBGrids.TDBgrid)
        function CanEditModify: Boolean; override;
        Property Col; // make property col visible
      End;
    
      TForm6 = class(TForm)
        DBGrid1: TDBGrid;
        ADOConnection1: TADOConnection;
        ADODataSet1: TADODataSet;
        DataSource1: TDataSource;
        ADODataSet1Componame: TStringField;
        ADODataSet1TrackTitle: TStringField;
      private
        { Private-Deklarationen }
      public
        { Public-Deklarationen }
      end;
    
    var
      Form6: TForm6;
    
    implementation
    
    {$R *.dfm}
    
    { TDBGrid }
    
    function TDBGrid.CanEditModify: Boolean;
    var
     f:TField;
     c:Integer;
    begin
      Result := inherited CanEditModify;
      c := Col;
      if dgIndicator in Options then dec(c); 
      F := Columns[c].Field;
      if Assigned(F) then
        begin // here just an example condition
          if (f.FieldName='TrackTitle') then
            if Pos('aa',F.AsString)>0 then Result := False;
          // you also can access the dataset via
          // if f.DataSet.FieldByName('xy').SomeCondition then ....    
        end;
    end;
    
    end.