TListView组件中的复选框无法滚动

3

我创建了一个ListView并添加了复选框以便需要时检查每一行。所有的都很好,直到列表中有很多项需要滚动。我在线上进行了检查,然后发现如果我滚动滚动条,复选框不会随着其他内容一起滚动。

我的代码:

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.

我需要在代码中添加什么,才能使复选框随其他内容一起滚动?


这是一个由http://www.alphaskins.com/制作的自定义ListView组件。 - evilone
我建议您联系控件供应商寻求支持。 - David Heffernan
@David,这段代码能在标准控件上运行吗? - evilone
1
你不会使用标准控件来完成这个操作,而是应该使用它的标准复选框。 - David Heffernan
@David,但是在另一个表单中,我想为每个列表视图行添加按钮,如果滚动不起作用,我该如何添加它们? - evilone
@evilone,再次联系此组件的供应商。 - David Heffernan
1个回答

6
标准ListView具有一个称为“复选框”的属性,可以将其设置为true。
如果使用它,则不必麻烦制作自己的复选框。
我从未在此控件中遇到复选框显示不正常的问题。

此属性在ViewStyle:=vsListViewStyle:= vsReport中最有效

或者,如果您只希望某些项拥有复选框,则制作一个复选框图片(1个未选中,1个已选中)并将其添加到ImageList中。
如果项目需要复选框,请将其ImageIndex属性设置为未选中项目的属性。 如果需要选中,则将其ImageIndex属性设置为选中图像。
此方法适用于ViewStyle:=vsReportViewStyle:=vsList

您正在使用自定义ListView TsListView控件,请尝试改用标准的ListView,看看是否会出现奇怪的行为。


好的,但是如果我想为列表项添加按钮而不是复选框呢?这个TsListView是可皮肤化组件,就像标准的ListView一样工作。 - evilone
2
@evilone,同样的操作,为按钮的每个状态创建图像,并根据需要更改“ImageIndex”。 - Johan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接