Установите некоторые ячейки в TDbGrid для редактирования

Я хочу, чтобы в TDBGrid редактировались только некоторые ячейки. В данном столбце некоторые, но не все ячейки будут доступны для редактирования, поэтому я не могу просто установить Column.ReadOnly для всего столбца, а затем оставить его таким.

Какие события лучше всего использовать, чтобы я мог получить контроль при входе в ячейку. Я мог бы использовать TDbGrid.ColumnEnter для обнаружения горизонтального движения и TDataSet.AfterScroll для вертикального движения в сетке. Или я мог бы использовать TDBGrid.DrawColumnCell (который я уже использую для изменения цвета некоторых ячеек...)

И у меня также возникли проблемы с определением лучшего способа изменить статус ячейки только для чтения. Я мог бы установить базовый TTable.Field.ReadOnly или TDbGrid.Columns[].ReadOnly.

Я мог бы поэкспериментировать со всем вышеперечисленным, но тогда я зависел бы от своего тестирования, чтобы определить, как реализована сетка, и мог бы упустить какую-то ситуацию. Я бы предпочел знать, предоставляет ли VCL способ справиться с этой потребностью, есть ли предостережения и т. д.

Связано: ячейка TDBGrid/TwwDBGrid только для чтения в Delphi?, но не обрабатывает прокрутка с помощью клавиатуры.


person RobertFrank    schedule 16.04.2013    source источник


Ответы (2)


Вы можете переопределить функцию CanEditModify и добавить желаемое условие. Это можно сделать, создав новый компонент с добавлением нового события или просто с помощью промежуточного класса.

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.
person bummi    schedule 16.04.2013
comment
Спасибо, бамми. Это дает мне отправную точку. Однако при компиляции в D7 некоторого кода, взятого из вашего образца, я получаю ошибку несовместимого типа в унаследованной строке. Кроме того, если я хочу, чтобы мое переопределение иногда возвращалось к базовым классам, является ли синтаксис Result := inherited; ?? БЛАГОДАРНОСТЬ! - person RobertFrank; 16.04.2013
comment
@RobertFrank В данный момент у меня нет D7. Я сделал правку... Вы должны всегда вызывать inherited, чтобы избежать неожиданного поведения, ваш код должен изменить или не изменить унаследованный результат. - person bummi; 16.04.2013
comment
Эта строка в Table1AfterScroll делает то, что мне нужно. Table1.FieldByName('MyFieldName').ReadOnly := ‹какое-то условие›; Когда я писал свой первоначальный пост, я не осознавал, что мое состояние зависит от записи и не зависит от горизонтального движения. Я помещаю это как комментарий, потому что я дам баллы за ответ, так как этот ответ был самым полезным и привел бы меня к ответу на мой первоначальный вопрос. - person RobertFrank; 16.04.2013

DBGrid решает, отображать ли текстовое поле редактирования на основе большого количества входных данных:

  1. Доступен ли сам DBGrid только для чтения.
  2. Доступен ли набор данных только для чтения
  3. Доступен ли столбец только для чтения
  4. Является ли поле доступным только для чтения
  5. Можно ли перевести набор данных в режим редактирования

Если вы хотите сделать некоторые ячейки в столбце DBGrid доступными для редактирования, а другие ячейки в том же столбце — недоступными для редактирования, вам придется сделать это самостоятельно. DBGrid просматривает набор данных для большинства своих сигналов с переопределением всей сетки и столбцов.

Я не помню, можно ли настроить поле набора данных CanModify для возврата разных значений true или false в зависимости от данных отдельной строки. Если да, то это, вероятно, ваш лучший вариант. DBGrid будет учитывать любое поле, возвращаемое CanModify.

Если CanModify не зависит от контекста каждой строки, вы можете использовать свою логику, чтобы решить, какие ячейки должны быть редактируемыми в CanEditModify. Создайте новый класс сетки, наследуемый от TDBGrid (или TCustomDBGrid), и переопределите виртуальный метод CanEditModify. Вероятно, вам следует сначала выполнить свою пользовательскую логику, а затем вызвать унаследованный метод, если ваша логика не применяется. Возможно, вам придется переопределить несколько других методов для точной настройки внешнего вида, например CanEditShow.

person dthorpe    schedule 16.04.2013