Set some cells in TDbGrid to editable

好久不见. 提交于 2020-01-11 11:52:28

问题


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.


回答1:


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.



回答2:


The DBGrid decides whether to show a text edit box based on a lot of inputs:

  1. Whether the DBGrid itself is read-only.
  2. Whether the dataset is read-only
  3. Whether the column is read-only
  4. Whether the field is read-only
  5. Whether the dataset can be put into edit mode

If you want to make some cells in a DBGrid column editable, and other cells in the same column not editable, you're going to have to do that yourself. The DBGrid looks to the dataset for most of its cues, with grid-wide and columnar overrides.

I don't recall if the dataset field CanModify can be configured to return different true or false based on individual row data. If so, this is probably your best option. The DBGrid will honor whatever field CanModify returns.

If CanModify isn't per-row contextual, you can put your logic to decide which cells should be editable in CanEditModify. Create a new grid class inheriting from TDBGrid (or TCustomDBGrid) and override the CanEditModify virtual method. You should probably do your custom logic first, then call the inherited method if your logic doesn't apply. You may need to override a few other methods to fine tune appearances, such as CanEditShow.



来源:https://stackoverflow.com/questions/16042975/set-some-cells-in-tdbgrid-to-editable

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!