Search code examples
delphidevexpresstcxgrid

Where is the TdxDBTreeListColumn.OnFilterStringUnformat analog in TcxGridDBBandedColumn?


We use the DevExpress ExpressQuantumGrid v3 (TdxDBGrid) and ExpressQuantumGrid Suite v12 (TcxGrid) in our application. With the TdxDBGrid, we use the TdxDBTreeListColumn.OnFilterStringFormat and OnFilterStringUnformat events to allow us to filter using string representations of values of the underlying datatype associated with the column. For example, we may have time periods stored in milliseconds, but displayed in HH:MM:SS format.

But I'm stuck with how do do this with the TcxGrid. While I can use the TcxGridDBBandedColumn.OnGetFilterDisplayText as an analog for TdxDBTreeListColumn.OnFilterStringFormat, I'm stuck with how to implement the functionality provided by TdxDBTreeListColumn.OnFilterStringUnformat, to ensure I can convert from the display value specified by the user to the value stored in the underlying dataset.

How is this functionality achieved with the TcxGrid?


Solution

  • I'm not sure I've understand your question 100%. I unsure what you mean by

    I'm stuck with how to implement the functionality provided by TdxDBTreeListColumn.OnFilterStringUnformat, to ensure I can convert from the display value specified by the user to the value stored in the underlying dataset.

    First of all I've made a small example:

    Added a new TdxMemtable with a Date Field in it, linked it to a tcxGrid and i've added some random data to it:

    procedure TForm1.FormCreate(Sender: TObject);
    var
      i: Integer;
      BeginOfYear: TDateTime;
    begin
      Randomize;
      dxMemData1.Active := true;
      dxMemData1.DisableControls;
      BeginOfYear := EncodeDate(2015, 1, 1);
    
      for i := 0 to 500 do
        dxMemData1.AppendRecord([i, Random(Trunc(Date - BeginOfYear)) + BeginOfYear]);
    
      dxMemData1.EnableControls;
    end;
    

    Then I've given the Column an OnGetFilterDisplayText event:

    procedure TForm1.cxGrid1DBTableView1Field2GetFilterDisplayText(Sender: TcxCustomGridTableItem; const AValue: Variant; var ADisplayText: string);
    begin
      if VarIsType(AValue, varDate) then
        ADisplayText := FormatDateTime(FormatSettings.LongDateFormat, AValue);
    end;
    

    And it gives me the result I wanted:

    with no OnGetFilterDisplayText event:

    enter image description here

    And with a OnGetFilterDisplayText event:

    enter image description here

    As you can see I've formated the text in the Filter box with out modifying the internal data.

    So the last thing is to display the data in the wanted format by adding an OnGetDataText to the colum :

    procedure TForm1.cxGrid1DBTableView1Field1GetDataText(Sender: TcxCustomGridTableItem; ARecordIndex: Integer; var AText: string);
    var
      aDateTime: TDateTime;
    begin
      if TryStrToDate(AText, aDateTime) then
        AText := FormatDateTime(FormatSettings.LongDateFormat, aDateTime);
    end;
    

    And here you have the result :

    enter image description here

    After:

    enter image description here

    By doing it this way you keep your data in your dataset in your internal format but displays it to the user diffrent.

    in order for showing you how to get the original data value and the datavalue on the Screen I've added two tcxEdit and a AfterScrollEcent to mu dataset:

    procedure TMainForm.gridDBTableView1FocusedRecordChanged(Sender: TcxCustomGridTableView; APrevFocusedRecord, AFocusedRecord: TcxCustomGridRecord; ANewItemRecordFocusingChanged: Boolean);
    var
      Index: Integer;
    begin
      if AFocusedRecord = nil then
        exit;
    
      Index := gridDBTableView1time_field.Index;
      cxTextEdit1.Text := AFocusedRecord.Values[Index];
      cxTextEdit2.Text := AFocusedRecord.DisplayTexts[Index];
    end;
    

    Here is the result :

    enter image description here

    So far we have out data displayed the way we wanted it, and filtering from the headder is posible, but ig you from the choose custom filtering you'll get an error.

    In order for making that work you need to create a TcxFilterComboBoxHelper descendant?

    type
      TmyFilterComboBoxHelper = class(TcxFilterComboBoxHelper)
      private
        class function TryLongDateFormatToDate(const S: string; out Value: TDateTime): Boolean;
        class function TryStringToMilliseconds(const S: string; out Value: Int64): Boolean;
      public
        class procedure GetFilterValue(AEdit: TcxCustomEdit; AEditProperties: TcxCustomEditProperties; var V: Variant; var S: TCaption); override;
      end;
    

    The complete code can be found here: http://pastebin.com/A1NRNg2J