delphi – TListView SelCount报告虚拟列表中错误的项目数
我需要启用或禁用按钮,具体取决于列表中是否至少选择了一行.
以下是重现此问题的代码.使用OnData事件填充列表,它允许选择多行. 我以为我可以使用OnSelectItem来检测用户何时更改选择,然后使用TListView SelCount函数来检测所选行的数量. 问题是当用户选择多行时,SelCount返回0.如果手动填充列表(即不通过OnData事件),这可以正常工作. 有任何想法吗? 谢谢 更新:使用OnChange事件似乎可以解决问题.仍然有趣的是,当选择多行时(从SelectItem事件中),SelCount为什么返回0. 另一个更新:我发布了一个测试项目:https://dl.dropboxusercontent.com/u/35370420/TestListView2.zip以及截图: ? 要重现此问题,请运行应用程序,选择Item1,然后按SHIFT单击Item2.该按钮被禁用.我的目的是只要在列表中选择了至少一个项目,就动态启用按钮.如果没有选定项目,则禁用该按钮. PAS文件: unit MainUnit; interface uses Winapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.Dialogs,Vcl.ComCtrls,Vcl.StdCtrls; type TForm3 = class(TForm) ListView1: TListView; Button1: TButton; procedure FormCreate(Sender: TObject); procedure ListView1Data(Sender: TObject; Item: TListItem); procedure ListView1SelectItem(Sender: TObject; Item: TListItem; Selected: Boolean); private { Private declarations } public { Public declarations } end; var Form3: TForm3; implementation {$R *.dfm} procedure TForm3.FormCreate(Sender: TObject); begin ListView1.Items.Count := 5; end; procedure TForm3.ListView1Data(Sender: TObject; Item: TListItem); begin Item.Caption := String.Format('Item%d',[Item.Index]); end; procedure TForm3.ListView1SelectItem(Sender: TObject; Item: TListItem; Selected: Boolean); begin Button1.Enabled := ListView1.SelCount > 0; OutputDebugString(pchar(String.Format('SelCount = %d',[ListView1.SelCount]))); end; end. 形成: object Form3: TForm3 Left = 0 Top = 0 Caption = 'Form3' ClientHeight = 600 ClientWidth = 952 Color = clBtnFace DoubleBuffered = True Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] OldCreateOrder = False OnCreate = FormCreate PixelsPerInch = 96 TextHeight = 13 object ListView1: TListView Left = 168 Top = 160 Width = 250 Height = 150 Columns = < item AutoSize = True Caption = 'Test' end> HideSelection = False MultiSelect = True OwnerData = True TabOrder = 0 ViewStyle = vsReport OnData = ListView1Data OnSelectItem = ListView1SelectItem end object Button1: TButton Left = 168 Top = 120 Width = 75 Height = 25 Caption = 'Some Action' Enabled = False TabOrder = 1 end end 解决方法
根本问题是当您SHIFT单击多个项目时,您将不会获得已选择的项目的任何OnSelectItem事件. SHIFT Click会首先取消选择所有列表视图项,在新项目被选中之前触发Item = nil和Selected = False的单个OnSelectItem事件.在该事件发生时,TListView.SelCount确实为0,因此您禁用了按钮,但是没有进一步的OnSelectItem事件告诉您已经选择了新项目,因此您不再检查SelCount以重新启用按钮.
当单个项目在选定和未选定之间更改状态时,或者当整个ListView中的所有项目更改为相同的选定/未选定状态时,将触发OnSelectItem事件以回复 procedure TForm3.ListView1DataStateChange(Sender: TObject; StartIndex,EndIndex: Integer; OldState,NewState: TItemStates); begin if (NewState * [isSelected]) <> (OldState * [isSelected]) then Button1.Enabled := ListView1.SelCount > 0; end; 因此,您需要使用OnSelectItem和OnDataStateChange来处理所有可能的选择/取消选择状态更改. 最佳解决方案是不对单个项目状态更改手动启用/禁用TButton.删除Form上的TActionManager,创建一个新的TAction并将其分配给TButton.Action属性,然后使用TAction.OnUpdate事件根据当前的TListView.SelCount启用/禁用TAction,例如: procedure TForm3.MyActionUpdate(Sender: TObject); begin MyAction.Enabled := ListView1.SelCount > 0; end; 每当主消息队列空闲时,包括在处理了ListView通知消息之后,这将自动启用/禁用关联的TButton.这样,无论使用哪种输入组合来选择/取消选择ListView项,都可以保持TButton的更新. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |