OZ8HP
OZ8HP

Reputation: 1513

Devexpress grid with unbound column

I have a DevExpress grid where I would like to add an unbound checkbox to be able to select some of the items. After the selection is made I press a button and I must loop the grid to get all the selected items. It has to be a checkbox. I have tried with a multiselectable grid, but the users can't work with that.

I have tried all the samples that I have been able to find on the supportsites, but no luck.

My question: does anyone have a working sample that shows how this can be done?

Upvotes: 3

Views: 4911

Answers (1)

shunty
shunty

Reputation: 3758

I've done this and it was (is!) pretty ugly! Create the grid view with bound columns and add an unbound checkbox column with a field type of boolean.

Basically I handle the OnCellClick of the grid view. I check if the item clicked is the checkbox column - by finding the first unbound column in the view with a checkbox type. Then I toggle its state.

I've set AutoEdit on the dataset to true but Deleting/Editing/Inserting to false and ImmediateEditor is false. Not exactly sure which of those are important.

I think the hardest thing was trying to fathom out the complex hierarchy of grid and view level objects and working out which levels contained which of the needed bits. I'm sure there's a better way of doing it but what we've got now works and I'm not going to touch it again!

This is lifted from my code but modified slightly and not tested as it stands - it also needs a bit more error checking:

procedure TMyForm.ViewCellClick(Sender: TcxCustomGridTableView;
  ACellViewInfo: TcxGridTableDataCellViewInfo; AButton: TMouseButton;
  AShift: TShiftState; var AHandled: Boolean);
var
  col: TcxGridColumn;
begin
  // Manually handle the clicking of the checkbox cell - otherwise it seems
  // virtually impossible to get the checked count correct.
  col := GetViewCheckColumn(Sender);
  if (Sender.Controller.FocusedItem = col) then
  begin
    ToggleRowSelection(TcxCustomGridTableView(TcxGridSite(Sender).GridView), col);
  end;
end;

procedure TMyForm.ToggleRowSelection(AView: TcxCustomGridTableView; ACol: TcxGridColumn);
var
  rec: TcxCustomGridRecord;
begin
  rec := AView.Controller.FocusedRecord;
  if (rec = nil) then exit;

  if (rec.Values[ACol.Index] = TcxCheckBoxProperties(ACol.Properties).ValueChecked) then
  begin
    rec.Values[ACol.Index] := TcxCheckBoxProperties(ACol.Properties).ValueUnchecked;
  end
  else
  begin
    rec.Values[ACol.Index] := TcxCheckBoxProperties(ACol.Properties).ValueChecked;
  end;
end;


function TMyForm.GetViewCheckColumn(AView: TcxCustomGridView): TcxGridColumn;
var
  index: integer;
  vw: TcxCustomGridTableView;
  item: TcxCustomGridTableItem;
begin
  // We're looking for an unbound check box column - we'll return the first
  // one found.

  Assert(AView <> nil);
  result := nil;
  if (AView is TcxCustomGridTableView) then
  begin
    vw := TcxCustomGridTableView(AView);
    for index := 0 to vw.ItemCount - 1 do
    begin
      item := vw.Items[index];
      if (item.Properties is TcxCustomCheckBoxProperties) then
      begin
        if (item is TcxGridDBColumn) then
        begin
          if (TcxGridDBColumn(item).DataBinding.FieldName = '') then
          begin
            result := TcxGridColumn(item);
            break;
          end;
        end;
      end;
    end;
  end;
end;

I then extended it by checking for a SPACE bar press in the OnKeyUp of the grid and calling ToggleRowSelection and also similar for a double click on a row.

When iterating through the rows you can test if a row is checked using something like the following:

function TMyForm.GetViewIsRowChecked(AView: TcxCustomGridView; ARecord: TcxCustomGridRecord): boolean;
var
  col: TcxGridColumn;
begin
  result := False;
  col := GetViewCheckColumn(AView);
  if ((col <> nil) and (ARecord <> nil)) then
  begin
    result := (ARecord.Values[col.Index] = TcxCheckBoxProperties(col.Properties).ValueChecked);
  end;
end;

I think that's it. I've dug it out of a large grid/view helper unit we've built up over a while. Oh, and it's currently working with Delphi 2010 with DXVCL v2011 vol 1.10.

Hope it helps.

Upvotes: 1

Related Questions