Reputation: 22750
I've created ListView and added checkboxes to check each row if needed. All was fine until there was a lot of items in the listview so that it needed scolling. I checked on line and then I saw that checkboxes are not scrolling with other content if I scroll the scrollbar.
My code:
unit ShareCommissionDialog;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, sButton, ComCtrls, sListView, sCheckBox, DataManager;
type
TdlgShareCommission = class(TForm)
lvEmployees: TsListView;
btnCancel: TsButton;
btnDone: TsButton;
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure btnDoneClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
private
manager: TDataManager;
ListViewCheckBoxList: TList;
employeeIDs: TStringList;
procedure ListViewCheckBoxCreate(List: TsListView; employeeID: string; R: TRect);
procedure ListViewCheckBoxClick(Sender: TObject);
procedure ListViewCheckBoxSelected(item: Integer; List: TsListView);
procedure ListViewCheckBoxUnselected(item: Integer; List: TsListView);
procedure PopulateEmployees;
procedure ShowSelectedEmployees;
procedure MarkRows;
public
property DataManager: TDataManager read manager write manager;
property CommissionReceivers: TStringList read employeeIDs write employeeIDs;
end;
var
dlgShareCommission: TdlgShareCommission;
implementation
{$R *.dfm}
procedure TdlgShareCommission.btnCancelClick(Sender: TObject);
begin
employeeIDs := employeeIDs;
end;
procedure TdlgShareCommission.btnDoneClick(Sender: TObject);
var
i, j: Integer;
begin
employeeIDs := TStringList.Create;
for i := 0 to ListViewCheckBoxList.Count - 1 do
begin
if TsCheckBox(ListViewCheckBoxList[i]).Checked then
begin
for j := 0 to manager.Data.Employees.Count - 1 do
begin
if TsCheckBox(ListViewCheckBoxList[i]).Tag = StrToInt(manager.Data.Employees[j].ID) then
begin
employeeIDs.Add(manager.Data.Employees[j].ID);
Break;
end;
end;
end;
end;
end;
procedure TdlgShareCommission.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
manager.GetEmployees(manager.Data.SelectedPOS.ID);
end;
procedure TdlgShareCommission.FormCreate(Sender: TObject);
begin
ListViewCheckBoxList := TList.Create;
end;
procedure TdlgShareCommission.ListViewCheckBoxCreate(List: TsListView; employeeID: string; R: TRect);
function NewViewCheckBox: TsCheckBox;
begin
Result := TsCheckBox.Create(Self);
Result.Tag := StrToInt(employeeID);
Result.Parent := List;
Result.BoundsRect := R;
Result.Checked := False;
Result.OnClick := ListViewCheckBoxClick;
end;
begin
ListViewCheckBoxList.Add(NewViewCheckBox);
end;
procedure TdlgShareCommission.FormShow(Sender: TObject);
begin
if employeeIDs <> nil then
begin
PopulateEmployees;
ShowSelectedEmployees;
MarkRows;
end
else
begin
PopulateEmployees;
MarkRows;
end;
//PopulateEmployees;
//MarkRows;
end;
procedure TdlgShareCommission.ListViewCheckBoxClick(Sender: TObject);
var
i: Integer;
begin
for i := 0 to ListViewCheckBoxList.Count - 1 do
begin
if (i+1) <= (ListViewCheckBoxList.Count - 1) then
if not TsCheckBox(ListViewCheckBoxList[i+1]).Enabled then
begin
TsCheckBox(ListViewCheckBoxList[i+1]).Checked := TsCheckBox(ListViewCheckBoxList[i]).Checked;
end;
end;
MarkRows;
end;
procedure TdlgShareCommission.MarkRows;
var
j: Integer;
begin
for j := 0 to lvEmployees.Items.Count - 1 do
begin
if not TsCheckBox(ListViewCheckBoxList[j]).Checked then
begin
ListViewCheckBoxSelected(j, lvEmployees);
end
else
begin
ListViewCheckBoxUnselected(j, lvEmployees);
end;
end;
end;
procedure TdlgShareCommission.ListViewCheckBoxSelected(item: Integer; List: TsListView);
begin
with List do
begin
Items[item].Selected := False;
end;
end;
procedure TdlgShareCommission.ListViewCheckBoxUnselected(item: Integer; List: TsListView);
begin
with List do
begin
Items[item].Selected := False;
end;
end;
procedure TdlgShareCommission.PopulateEmployees;
var
i: Integer;
R: TRect;
employeeRow: TListItem;
begin
with lvEmployees do
try
Items.BeginUpdate;
Items.Clear;
manager.GetEmployees(manager.Data.SelectedPOS.ID);
for i := 0 to manager.Data.Employees.Count - 1 do
begin
employeeRow := Items.Add;
R := Items[i].DisplayRect(drBounds);
R.Left := 5;
R.Top := R.Top + 1;
ListViewCheckBoxCreate(lvEmployees, manager.Data.Employees[i].ID, R);
Items[i].Data := TsCheckBox(ListViewCheckBoxList[i]);
employeeRow.SubItems.Add(manager.Data.Employees[i].FirstName + ' ' + manager.Data.Employees[i].LastName);
end;
finally
lvEmployees.Items.EndUpdate;
end;
end;
procedure TdlgShareCommission.ShowSelectedEmployees;
var
i, j: Integer;
begin
for j := 0 to lvEmployees.Items.Count - 1 do
begin
for i := 0 to employeeIDs.Count - 1 do
begin
if TsCheckBox(ListViewCheckBoxList[j]).Tag = StrToInt(employeeIDs[i]) then
begin
TsCheckBox(ListViewCheckBoxList[j]).Checked := True;
end;
end;
end;
end;
end.
What I need to add to code that checkboxes also will scroll with other content?
Upvotes: 3
Views: 826
Reputation: 76753
The standard ListView has a property called checkboxes
that can be set to true.
If you use that then you don't have to mess with making your own checkboxes.
I've never had any problems with checkboxes not showing properly in this control.
This property works best in ViewStyle:= vsList
or ViewStyle:= vsReport
Alternatively if you want checkboxes on some items but not on others
then make a picture of a checkbox (1 unchecked, 1 checked) and add both of them to an ImageList.
If an item needs a checkbox, set its ImageIndex property to that of the unchecked item. If it needs to be checked, set its ImageIndex property to the checked Image.
This works in ViewStyle:= vsReport
and ViewStyle:= vsList
.
You are using a custom ListView (TsListView
) control, try using a standard ListView instead and see if the strange behaviour shows up.
Upvotes: 6