Jump to content


Photo

[5.0] Restricting cell editing?


  • Please log in to reply
5 replies to this topic

#1 littlebigfred

littlebigfred
  • Members
  • 176 posts

Posted 07 September 2009 - 01:51 PM

Hello,

I'd like to build a two-column grid like this to display a set of key=value.

Here are the requirements:
  1. The user must only be able to change the value that matches Key2. Other values must remain read-only
  2. The user must be able to navigate and select a value cell either by using the up/down arrow keys, or by single-clicking on the cell
  3. Once a value cell has been selected, we make sure the value matches Key2, and if yes, the grid must switch to edit mode either through F2 (like Excel), through Enter, or by clicking a second time on the cell (since the user has already clicked once to select the cell -> a second click means switching to edit mode)


The reason I don't want users to switch to edit mode simply by starting typing, is that I want to reduce the risk of errors by making them switch to edit mode explicitely through either F2/Enter or double-click.

How can modify the grid so that it satisfies the requirements above?

FWIW, here's the code I used to display the two-column grid above.

Thank you.

#2 littlebigfred

littlebigfred
  • Members
  • 176 posts

Posted 07 September 2009 - 02:05 PM

This code doesn't solve the issue

CODE
procedure TForm1.NextGrid1CellDblClick(Sender: TObject; ACol,
  ARow: Integer);
begin
  //How to let user edit cell?
end;

procedure TForm1.NextGrid1KeyPress(Sender: TObject; var Key: Char);
begin
  //if Key = VK_F2 then begin
  //BAD too
  if Key = 'VK_F2' then begin
    With NextGrid1 do begin
      If Cell[0,SelectedRow].AsString = 'Key2' then begin
        OnDblClick;
      end;
    end;
  end;
end;


#3 littlebigfred

littlebigfred
  • Members
  • 176 posts

Posted 07 September 2009 - 02:23 PM

I have an additional requirement: Since the Key column is read-only at all times, the user shouldn't be able to click/navigate to this column. Only the up/down arrow should work, not the left/right.

#4 deonvn

deonvn

    Senior Member

  • Honorable Members
  • PipPip
  • 313 posts

Posted 07 September 2009 - 02:37 PM

Hi

Try this:

CODE
procedure TForm2.FormActivate(Sender: TObject);
begin
  With NextGrid1 do begin
    //What for?
    //AppearanceOptions := AppearanceOptions + [aoHideFocus];

    //Second parameter = caption, not name
    Columns.Add(TNxTextColumn,'Key');
    Columns.Add(TNxTextColumn,'Value');
    Columns[0].Name := 'Key';
    Columns[1].Name := 'Value';

    FixedCols := 1;
    Columns[0].DrawingOptions := doCustomOnly;

Columns[0].Enabled := False;

    //To avoid mistakes, user must explicitely switch to edit mode
    //Columns[1].Options := Columns[1].Options + [coAutoSize,coEditing];


NextGrid1.Options := NextGrid1.Options + [goSecondClickEdit];
Columns[1].Options := Columns[1].Options + [coEditing];


    Columns[1].Options := Columns[1].Options + [coAutoSize];
    AddRow(2);

    CellsByName['Key', 0] := 'key1';
    CellsByName['Value', 0] := 'value1';
    CellsByName['Key', 1] := 'key2';
    CellsByName['Value', 1] := 'value2';
  end;
end;

procedure TForm2.NextGrid1BeforeEdit(Sender: TObject; ACol, ARow: Integer;
  var Accept: Boolean);
begin
  Accept := TNextGrid(Sender).Cell[ACol - 1,ARow].AsString = 'key2';
end;

procedure TForm2.NextGrid1CustomDrawCell(Sender: TObject; ACol, ARow: Integer;
  CellRect: TRect; CellState: TCellState);
var
  R: TRect;
begin
  with NextGrid1.Canvas do begin
    R := CellRect;
    Frame3D(NextGrid1.Canvas, R, clBtnHighlight, clBtnShadow, 1);
    Brush.Color := clBtnFace;
    FillRect(R);
    TextRect(R, CellRect.Left + 4, CellRect.Top + 2, NextGrid1.Cells[ACol, ARow]);
  end;
end;

procedure TForm2.NextGrid1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key in [VK_RETURN, VK_F2] then
    if NextGrid1.RowExist(NextGrid1.SelectedRow) then
      if not(gtEdit in NextGrid1.GridState) then
        NextGrid1.EditCell(NextGrid1.SelectedColumn,NextGrid1.SelectedRow);
end;


It is not a complete solution, but it will put you on the right track.

Regards,

Deon

#5 littlebigfred

littlebigfred
  • Members
  • 176 posts

Posted 07 September 2009 - 03:50 PM

Thanks much for the tip.

Out of curiosity, what is the order in which events are triggered, considering that the column is configured to be read-only by default?

Is it KeyDown -> EditCell -> BeforeEdit, or BeforeEdit -> KeyDown -> EditCell?

#6 littlebigfred

littlebigfred
  • Members
  • 176 posts

Posted 07 September 2009 - 03:55 PM

For those interested, after reading the archives and trying a few things, here's some code that lets the user edit the cell where column = Value and row = key2, either by hitting F2 or double-clicking on the cell:

CODE
procedure TForm1.FormActivate(Sender: TObject);
begin
  With NextGrid1 do begin
    //Second parameter = caption, not name
    Columns.Add(TNxTextColumn,'Key');
    Columns.Add(TNxTextColumn,'Value');
    Columns[0].Name := 'Key';
    Columns[1].Name := 'Value';

    FixedCols := 1;

    //To avoid mistakes, user must explicitely switch to edit mode
    //Columns[1].Options := Columns[1].Options + [coAutoSize,coEditing];
    Columns[1].Options := Columns[1].Options + [coAutoSize];
    AddRow(2);

    CellsByName['Key', 0] := 'key1';
    CellsByName['Value', 0] := 'value1';
    CellsByName['Key', 1] := 'key2';
    CellsByName['Value', 1] := 'value2';
  end;
end;

//Allow editing if column=Value and row=key2
procedure TForm1.SwitchToEditMode;
begin
  with NextGrid1 do begin
    if SelectedColumn = ColumnByName['Value'].Index  then begin
      if Cells[ColumnByName['Key'].Index,SelectedRow] = 'key2' then begin
        Columns[SelectedColumn].Options := Columns[SelectedColumn].Options + [coEditing];
        EditCell(SelectedColumn, SelectedRow);
      end;
    end;
  end;
end;

//Both CellDblClick and F2 call the same routine
procedure TForm1.NextGrid1CellDblClick(Sender: TObject; ACol,
  ARow: Integer);
begin
  SwitchToEditMode;
end;

procedure TForm1.NextGrid1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Key = vk_F2) then begin
    SwitchToEditMode;
  end;
end;

//Go back to read-only
procedure TForm1.NextGrid1AfterEdit(Sender: TObject; ACol, ARow: Integer;
  Value: WideString);
begin
  with NextGrid1 do begin
    Columns[SelectedColumn].Options := Columns[SelectedColumn].Options - [coEditing];
  end;
end;


HTH,




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users