Search code examples
delphidelphi-2007devart

How to access the search text in a TCRDBGrid component?


Is there a way to access the text entered in a Devart (Core Lab) TCRDBGrid search bar?

I tried implementing the OnKeyDown event but the event didn't happen during entry in the search fields, only when the grid itself was selected. There are no other events that look relevant.

The text appears to go into a TEdit which is part of a TCRGridTitleEdit, which is part of TCRDBGrid but is private.

Is there a way to get the search text?

Example TCFGBGrid:

+---------+------------+
| UserId  |  UserName  | <- Column titles
+---------+------------+
|[987654] | [        ] | <- Search bar (searching for UserId 987654)
+---------+------------+
| 123456  |  Wile Cau  | <- Data
+---------+------------+
|   ...   |    ...     | <- More data

If UserId 987654 doesn't exist, I want to prompt something like "Create new user 987654?" and potentially create a new record with UserId set to 987654.


Solution

  • TCRDBGrid is distributed with source code. You can modify source code:

    declare the event type:

      TOnTextChanged = procedure (Sender: TObject; Text: string) of object;
    

    add event declaration in the TCRGridTitleEdit class:

    private 
        FOnFilterChanged: TOnTextChanged;
        FOnSearchChanged: TOnTextChanged;
    
    public
        property OnFilterChanged: TOnTextChanged read FOnFilterChanged write FOnFilterChanged;
        property OnSearchChanged: TOnTextChanged read FOnSearchChanged write FOnSearchChanged;
    

    call this event in the ProcessEdit procedure:

    procedure TCRGridTitleEdit.ProcessEdit;
    begin
      if (FActiveColumn = nil) or (CRDBGrid = nil) or not FEdit.Modified then
        Exit;
    
      if FAsFilter then
        with CRDBGrid do begin
          try
            TCRColumn(FActiveColumn).GetFilterExpression(FEdit.Text);
            FFilterExpressions[FActiveColumn.Index] := FEdit.Text;
            Self.Caption := FFilterExpressions[FActiveColumn.Index];
            if Assigned(FOnFilterChanged) then
              FOnFilterChanged(self, FEdit.Text);
          except
            on EConvertError do begin
              FEdit.SelectAll;
              raise;
            end;
          end;
        end
      else
        try
          with FActiveColumn.Field do
            DataSet.Locate(FieldName, {$IFDEF CLR}Variant{$ENDIF}(FEdit.Text), [loCaseInsensitive,loPartialKey]);
          if Assigned(FOnSearchChanged) then
            FOnSearchChanged(self, FEdit.Text);
        except
          on EConvertError do
            Exit;
        end;
    end;
    

    and add event declaration in the TCRDBGrid class:

    private
      function GetOnFilterChanged: TOnTextChanged;
      procedure SetOnFilterChanged(Value: TOnTextChanged);
      function GetOnSearchChanged: TOnTextChanged;
      procedure SetOnSearchChanged(Value: TOnTextChanged);
    
    published
      property OnFilterChanged: TOnTextChanged read GetOnFilterChanged write SetOnFilterChanged;
      property OnSearchChanged: TOnTextChanged read GetOnSearchChanged write SetOnSearchChanged;
    

    implementation

    function TCRDBGrid.GetOnFilterChanged: TOnTextChanged;
    begin
      Result := CRGridTitleEdit.OnFilterChanged;
    end;
    
    procedure TCRDBGrid.SetOnFilterChanged(Value: TOnTextChanged);
    begin
      CRGridTitleEdit.OnFilterChanged := Value;
    end;
    
    function TCRDBGrid.GetOnSearchChanged: TOnTextChanged;
    begin
      Result := CRGridTitleEdit.OnSearchChanged;
    end;
    
    procedure TCRDBGrid.SetOnSearchChanged(Value: TOnTextChanged);
    begin
      CRGridTitleEdit.OnSearchChanged := Value;
    end;