Search code examples
delphidevexpresstcxgrid

cxGrid : instead of "go to next cell on enter" using "enter" do that with the arrow keys


Is there a way I can achieve cxGrid's functionality "go to next cell on enter" but using arrow keys on the keyboard instead of hitting "enter" ???

Right now I can navigate with the arrow keys but the cells I move to are not selected (blue color). If I edit a cell in the column and move to the cell beneath it (with the arrow key) , the grid jumps to some other random record in the grid,which is annoying.

Is it a question of settings or must you program this functionality ?

edit : This is a simple temporary table that I use to gather data. It has no indexed fields or autoinc field :

procedure TForm3.cxButton1Click(Sender: TObject);
begin
DataModule2.ACRQuery2.Close;
DataModule2.ACRQuery2.SQL.Clear;
DataModule2.ACRQuery2.SQL.Text :='insert into TEMP select company_id,member_id,surname,name from MEMBERS where company_id =:a1';
DataModule2.ACRQuery2.Params.ParamByName('a1').Value :=cxLookupComboBox2.Text;
DataModule2.ACRQuery2.ExecSQL;

DataModule2.ACRQuery3.Close;
DataModule2.ACRQuery3.SQL.Clear;
DataModule2.ACRQuery3.SQL.Text :='update temp set month=:a1,year=:a2';
DataModule2.ACRQuery3.Params.ParamByName('a1').Value :=cxComboBox2.Text;
DataModule2.ACRQuery3.Params.ParamByName('a2').Value :=cxTextEdit2.Text;
DataModule2.ACRQuery3.ExecSQL;

DataModule2.TEMP.Refresh;
end;

Data loads but when i edit the first record and move with the arrow down, the cursor jumps to the end of the grid .

enter image description here

Navigation with the arrow key functions normally.I can scroll down the column without problem and edit any record I pause on. But as soon as I edit it and move to the next record, the cursor jumps somwhere else. It seems the sync does not function. I really dont know. I am not sorting in any way .

The temp table : enter image description here


Solution

  • Is it a question of settings or must you program this functionality ?

    Yes, it is a question of settings and it doesn't require any code. However, there is evidently a problem in your project which I think you need to sort out first.

    When you say "the grid jumps to some other random record in the grid,which is annoying.", it sounds as if you are starting from the the wrong place to try and get the navigation behaviour you want because jumping like that certainly shouldn't happen. And it doesn't in any cxGrid project of mine.

    Anyway, I find that the representation of a cxGridDBTableView in the Object Inspector sometimes makes it hard to "see the wood for the trees". What I do then is to use a project which creates the grid entirely in code - see below.

    The code below is completely self-contained and doesn't require any event handlers, persistent TFields, etc. If you try it, you should find that by default, as created, the grid does support up and down and left and right cell navigation using the cursor keys. The only exception is that the left and right keys don't work for cell navigation when the current cell contents are being edited. However, if you uncomment the line

      cxView.DataController.Options := cxView.DataController.Options + [dcoImmediatePost];
    

    then, pressing Enter while editing in a cell immediately posts the edit back to the dataset, and the grid will allow you to navigate out of the cell by using the left- or right-arrow key. I'm sure there are fancier ways of achieving this effect by processing the key handling in code, but at least the dcoImmediatePost method has the advantage of requiring no code.

    When the app starts, you should see the see the top row "highlighted" (colored blue by default) except for its LH cell, which is focused.

    Hopefully, this example will help you identify the cause of the "jumping" in your project and may also help you refine your description of what you would like to obtain, in terms of cursor-key navigation.

    Code

    procedure TForm1.CreateGrid;
    begin
      cxGrid := TcxGrid.Create(Self);
      cxGrid.Parent := Self;
      cxGrid.Width := 400;
    
      cxLevel := cxGrid.Levels.Add;
      cxLevel.Name := 'Firstlevel';
    
      cxView := cxGrid.CreateView(TcxGridDBTableView) as TcxGridDBTableView;
      cxView.Name := 'ATableView';
      //  Uncomment the following line to make the grid respond to the `Enter` key by posting any pending change to the data row
      //    cxView.DataController.Options := cxView.DataController.Options + [dcoImmediatePost];
    
      cxView.DataController.KeyFieldNames := 'ID';
    
      cxLevel.GridView := cxView;
    
      cxView.DataController.DataSource := DS1;
    
      cxView.DataController.CreateAllItems;
    
    end;
    
    function CreateField(AFieldClass : TFieldClass; AOwner : TComponent; ADataSet : TDataSet;
    AFieldName, AName : String; ASize : Integer; AFieldKind : TFieldKind) : TField;
    begin
      Result := AFieldClass.Create(AOwner);
      Result.FieldKind := AFieldKind;
      Result.FieldName := AFieldName;
      Result.Name := AName;
      Result.Size := ASize;
      Result.DataSet := ADataSet;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      i : Integer;
      Field : TField;
    begin
    
      Field := CreateField(TAutoIncField, Self, CDS1, 'ID', 'CDS1ID', 0, fkData);
      Field := CreateField(TBooleanField, Self, CDS1, 'Marked', 'CDS1Marked', 0, fkData);
      Field := CreateField(TStringField, Self, CDS1, 'Name', 'CDS1Namefield', 20, fkData);
      Field := CreateField(TStringField, Self, CDS1, 'Value', 'CDS1Valuefield', 20, fkData);
    
      CDS1.CreateDataSet;
    
      CDS1.IndexFieldNames := 'ID';
    
      for i := 1 to 5 do begin
        CDS1.Insert;
        CDS1.FieldByName('Marked').AsBoolean := Odd(i);
        CDs1.FieldByName('Name').AsString := 'Name' + IntToStr(i);
        CDs1.FieldByName('Value').AsString := 'Value  ' + IntToStr(i);
        CDS1.Post;
      end;
    
      CDS1.First;
    
      CreateGrid;
    
      ActiveControl := cxGrid;
    
    end;