unit uViewDetallesGenerico; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, uViewBase, cxStyles, cxCustomData, cxGraphics, cxFilter, cxData, cxDataStorage, cxEdit, DB, cxDBData, cxTextEdit, ActnList, ImgList, PngImageList, uDADataTable, ComCtrls, ToolWin, cxGridLevel, cxGridCustomTableView, cxGridTableView, cxGridDBTableView, cxClasses, cxControls, cxGridCustomView, cxGrid, uDAInterfaces; type TfrViewDetallesGenerico = class(TfrViewBase) cxGrid: TcxGrid; cxGridView: TcxGridDBTableView; cxGridViewID: TcxGridDBColumn; cxGridLevel: TcxGridLevel; ToolBar1: TToolBar; ToolButton1: TToolButton; ToolButton2: TToolButton; dsDetalles: TDADataSource; ContenidoImageList: TPngImageList; ActionListContenido: TActionList; actAnadir: TAction; actEliminar: TAction; ToolButton4: TToolButton; actModificar: TAction; ToolButton5: TToolButton; ToolButton6: TToolButton; actAnchoAutomatico: TAction; ToolButton7: TToolButton; procedure cxGridViewEditKeyDown(Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem; AEdit: TcxCustomEdit; var Key: Word; Shift: TShiftState); procedure actAnadirExecute(Sender: TObject); procedure actEliminarExecute(Sender: TObject); procedure actEliminarUpdate(Sender: TObject); procedure actAnadirUpdate(Sender: TObject); procedure actAnchoAutomaticoExecute(Sender: TObject); procedure actModificarUpdate(Sender: TObject); procedure actModificarExecute(Sender: TObject); protected function HayDatos : Boolean; procedure AnadirInterno; virtual; procedure ModificarInterno; virtual; procedure EliminarInterno; virtual; function GetModified: Boolean; override; end; implementation {$R *.dfm} uses uDataTableUtils; procedure TfrViewDetallesGenerico.actAnadirExecute(Sender: TObject); var bEsMultiSelect : Boolean; begin // Debo quitar el multiselect porque provoca que se quede seleccionado // el registro actual y no el nuevo registro que voy a añadir bEsMultiSelect := cxGridView.OptionsSelection.MultiSelect; if bEsMultiSelect then cxGridView.OptionsSelection.MultiSelect := False; cxGridView.BeginUpdate; try if cxGridView.Controller.EditingController.IsEditing then cxGridView.Controller.EditingController.Edit.PostEditValue; AnadirInterno; finally cxGridView.EndUpdate; // Dejo la propiedad MultiSelect como estaba if bEsMultiSelect then cxGridView.OptionsSelection.MultiSelect := bEsMultiSelect; end; end; procedure TfrViewDetallesGenerico.actAnadirUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := Assigned(dsDetalles.DataTable); end; procedure TfrViewDetallesGenerico.actAnchoAutomaticoExecute(Sender: TObject); begin inherited; cxGridView.ApplyBestFit; end; procedure TfrViewDetallesGenerico.actEliminarExecute(Sender: TObject); var AuxTop, AuxRow:Integer; begin cxGridView.BeginUpdate; AuxTop := cxGridView.Controller.TopRowIndex; AuxRow := cxGridView.DataController.FocusedRowIndex; try EliminarInterno; //Selecciona en el grid el registro siguiente if (AuxRow < cxGridView.DataController.RowCount-1) then Inc(AuxRow) else Dec(AuxRow); if dsDetalles.DataTable.RecordCount > 0 then begin cxGridView.DataController.SelectRows(AuxRow,AuxRow); cxGridView.Controller.TopRowIndex := AuxTop; end; finally cxGridView.EndUpdate; end; end; procedure TfrViewDetallesGenerico.actEliminarUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := HayDatos; end; procedure TfrViewDetallesGenerico.actModificarExecute(Sender: TObject); begin inherited; ModificarInterno; end; procedure TfrViewDetallesGenerico.actModificarUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := HayDatos and (cxGridView.DataController.FocusedRowIndex >= 0) end; procedure TfrViewDetallesGenerico.AnadirInterno; begin dsDetalles.DataTable.Insert; end; procedure TfrViewDetallesGenerico.cxGridViewEditKeyDown( Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem; AEdit: TcxCustomEdit; var Key: Word; Shift: TShiftState); begin inherited; cxGridView.BeginUpdate; try Case Key of VK_DOWN : begin //En el caso de ser la última fila hacemos un append nosotros no el grid //ya que se saltaria la lógica del controllerDetallesBase if cxGridView.Controller.IsFinish then begin Key := 0; if Sender.Controller.EditingController.IsEditing then Sender.Controller.EditingController.Edit.PostEditValue; actAnadir.Execute; end; end; VK_RETURN, VK_RIGHT : begin //En el caso de ser la última fila hacemos un append nosotros no el grid //ya que se saltaria la lógica del controllerDetallesBase if cxGridView.Controller.IsFinish and AItem.IsLast then begin Key := 0; if Sender.Controller.EditingController.IsEditing then Sender.Controller.EditingController.Edit.PostEditValue; actAnadir.Execute; end; end; end; finally cxGridView.EndUpdate; end; end; procedure TfrViewDetallesGenerico.EliminarInterno; begin dsDetalles.DataTable.Delete; end; function TfrViewDetallesGenerico.GetModified: Boolean; begin Result := DataTableModified(dsDetalles.DataTable) or inherited GetModified; end; function TfrViewDetallesGenerico.HayDatos: Boolean; begin Result := Assigned(dsDetalles.DataTable) and (cxGridView.ViewInfo.VisibleRecordCount > 0) end; procedure TfrViewDetallesGenerico.ModificarInterno; begin // end; end.