unit uGridStatusUtils; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, cxCustomData, cxGraphics, cxFilter, cxData, cxDataStorage, cxEdit, DB, cxDBData, cxGridLevel, cxClasses, cxControls, cxGridCustomView, cxGridCustomTableView, cxGridTableView, cxGridDBTableView, cxGrid, uDBSelectionListUtils; type TRecordInfo = class KeyValues: Variant; ALevel: Integer; end; TRecordInfos = class(TList) private function GetItem(Index: Integer): TRecordInfo; protected procedure Notify(Ptr: Pointer; Action: TListNotification); override; public property Items[Index: Integer]: TRecordInfo read GetItem; Default; end; TcxGridStatus = class protected GroupRecords: TRecordInfos; SelectedRecords: TRecordInfos; SelStartItem: Integer; SelEndItem: Integer; AFocusedRow: TRecordInfo; TopRow: TRecordInfo; function SaveRecord(AView: TcxGridDBTableView; GridRecord: TcxCustomGridRecord): TRecordInfo; function FindRecordEx(AView: TcxGridDBTableView; RecordInfo: TRecordInfo): TcxCustomGridRecord; procedure SaveGridViewSelection(AView: TcxGridDBTableView); procedure LoadGridViewSelection(AView: TcxGridDBTableView); procedure SaveGridViewTopFocusedRecords(AView: TcxGridDBTableView); procedure LoadGridViewTopFocusedRecords(AView: TcxGridDBTableView); procedure SaveGridViewExpanded(AView: TcxGridDBTableView); procedure LoadGridViewExpanded(AView: TcxGridDBTableView); public constructor Create(AGridView: TcxGridDBTableView); destructor Destroy; override; procedure Restore(AGridView: TcxGridDBTableView); end; procedure SeleccionarFilasDesdeGrid(const AView : TcxGridDBTableView; ASelectedRowList : TSelectedRecords); implementation uses uDADataTable, uDAInterfaces, cxVariants; {$REGION 'TRecordInfos'} procedure TRecordInfos.Notify(Ptr: Pointer; Action: TListNotification); begin if Action in [lnExtracted, lnDeleted] then FreeAndNil(TRecordInfo(Ptr)); end; function TRecordInfos.GetItem(Index: Integer): TRecordInfo; begin Result := TRecordInfo(inherited Items[Index]); end; function TcxGridStatus.SaveRecord(AView: TcxGridDBTableView; GridRecord: TcxCustomGridRecord): TRecordInfo; begin Result := TRecordInfo.Create; Result.KeyValues := AView.DataController.GetRecordId(GridRecord.RecordIndex); Result.ALevel := GridRecord.Level; end; function TcxGridStatus.FindRecordEx(AView: TcxGridDBTableView; RecordInfo: TRecordInfo): TcxCustomGridRecord; var I, ARecordIndex: Integer; AList: TList; AKeyValue: Variant; begin I := 0; Result := nil; if not Assigned(RecordInfo) then Exit; ARecordIndex := AView.DataController.FindRecordIndexByKey(RecordInfo.KeyValues); AList := TList.Create; try while I < AView.ViewData.RowCount do begin if AView.ViewData.Rows[I] is TcxGridGroupRow then begin AList.Clear; AView.DataController.Groups.LoadRecordIndexesByRowIndex(AList, I); if AList.IndexOf(Pointer(ARecordIndex)) <> -1 then begin if AView.ViewData.Rows[I].Level < RecordInfo.ALevel then AView.ViewData.Rows[I].Expand(False) else begin Result := AView.ViewData.Rows[I]; Break; end; end; end else begin AKeyValue := AView.DataController.GetRecordId(AView.ViewData.Rows[I].RecordIndex); if VarEquals(AKeyValue, RecordInfo.KeyValues) then begin Result := AView.ViewData.Rows[I]; Break; end; end; Inc(I); end; finally FreeAndNil(AList); end; end; procedure TcxGridStatus.SaveGridViewSelection( AView: TcxGridDBTableView); var i: Integer; SelectRecordInfo: TRecordInfo; begin with AView.DataController, AView.Controller do begin for i := 0 To SelectedRecordCount - 1 do begin SelectRecordInfo := SaveRecord(AView, SelectedRecords[i]); Self.SelectedRecords.Add(SelectRecordInfo); end; if SelectedColumnCount = 0 then begin SelStartItem := -1; SelEndItem := -1; end else begin SelStartItem := SelectedColumns[0].Index; SelEndItem := SelectedColumns[SelectedColumnCount - 1].Index; end; end; end; procedure TcxGridStatus.LoadGridViewSelection( AView: TcxGridDBTableView); var i: Integer; ARecord: TcxCustomGridRecord; begin AView.Controller.ClearSelection; for i := 0 To SelectedRecords.Count - 1 do begin ARecord := FindRecordEx(AView, SelectedRecords[i]); if Assigned(ARecord) then ARecord.Selected := True; end; if SelStartItem <> -1 then AView.Controller.SelectColumns(AView.Columns[SelStartItem], AView.Columns[SelEndItem]); end; procedure TcxGridStatus.SaveGridViewTopFocusedRecords(AView: TcxGridDBTableView); begin if AView.Controller.FocusedRow = nil then AFocusedRow := nil else AFocusedRow := SaveRecord(AView, AView.Controller.FocusedRow); TopRow := nil; if (AView.Controller.TopRowIndex <> -1) and (AView.Controller.TopRowIndex < AView.ViewData.RecordCount) then TopRow := SaveRecord(AView, AView.ViewData.Records[AView.Controller.TopRowIndex]); end; procedure TcxGridStatus.LoadGridViewTopFocusedRecords(AView: TcxGridDBTableView); var ARecord: TcxCustomGridRecord; begin if Assigned(AFocusedRow) then begin ARecord := FindRecordEx(AView, AFocusedRow); if Assigned(ARecord) then ARecord.Focused := True; ARecord := FindRecordEx(AView, TopRow); if Assigned(ARecord) then AView.Controller.TopRowIndex := ARecord.Index; end; end; type TcxDataControllerGroupsAccess = class(TcxDataControllerGroups); TcxDataGroupsAccess = class(TcxDataGroups); procedure TcxGridStatus.SaveGridViewExpanded( AView: TcxGridDBTableView); var i: Integer; GroupRecordInfo: TRecordInfo; begin for i := 0 To AView.DataController.RowCount - 1 do with AView.ViewData.Records[i] do if Expanded then begin GroupRecordInfo := SaveRecord(AView, AView.ViewData.Records[i]); GroupRecords.Add(GroupRecordInfo); end; end; procedure TcxGridStatus.LoadGridViewExpanded( AView: TcxGridDBTableView); var i: Integer; ARecord: TcxCustomGridRecord; begin for i := 0 to GroupRecords.Count - 1 do begin ARecord := FindRecordEx(AView, GroupRecords[i]); if Assigned(ARecord) then ARecord.Expand(False); end; end; constructor TcxGridStatus.Create(AGridView: TcxGridDBTableView); begin inherited Create; GroupRecords := TRecordInfos.Create; SelectedRecords := TRecordInfos.Create; SaveGridViewSelection(AGridView); SaveGridViewExpanded(AGridView); SaveGridViewTopFocusedRecords(AGridView); end; destructor TcxGridStatus.Destroy; begin FreeAndNil(GroupRecords); FreeAndNil(SelectedRecords); inherited; end; procedure TcxGridStatus.Restore(AGridView: TcxGridDBTableView); begin SendMessage(AGridView.Site.Handle, WM_SETREDRAW, 0, 0); try AGridView.ViewData.Collapse(True); LoadGridViewExpanded(AGridView); LoadGridViewSelection(AGridView); LoadGridViewTopFocusedRecords(AGridView); finally SendMessage(AGridView.Site.Handle, WM_SETREDRAW, 1, 0); RedrawWindow(AGridView.Site.Handle, Nil, 0, RDW_FRAME Or RDW_NOFRAME Or RDW_ALLCHILDREN Or RDW_INVALIDATE); end; end; procedure SeleccionarFilasDesdeGrid(const AView : TcxGridDBTableView; ASelectedRowList : TSelectedRecords); var ARecord: TcxCustomGridRecord; i : Integer; AGridStatus : TcxGridStatus; begin if not Assigned(AView) then raise Exception.Create('No hay vista asignada (SeleccionarFilasDesdeGrid)'); ShowHourglassCursor; AGridStatus := TcxGridStatus.Create(AView); AView.BeginUpdate; try ASelectedRowList.Clear; for i := 0 to TcxCustomGridTableController(AView.Controller).SelectedRecordCount - 1 do begin ARecord := TcxCustomGridTableController(AView.Controller).SelectedRecords[i]; if (ARecord is TcxGridDataRow) then begin (ARecord as TcxGridDataRow).Focused := True; ASelectedRowList.CurrentRowSelected := True; end; end; finally AView.EndUpdate; AGridStatus.Restore(AView); FreeANDNIL(AGridStatus); HideHourglassCursor; end; end; {$ENDREGION} end.