delphi – TListView SelCount报告虚拟列表中错误的项目数

delphi – TListView SelCount报告虚拟列表中错误的项目数,第1张

概述我需要启用或禁用按钮,具体取决于列表中是否至少选择了一行. 以下是重现此问题的代码.使用OnData事件填充列表,它允许选择多行. 我以为我可以使用OnSelectItem来检测用户何时更改选择,然后使用TListView SelCount函数来检测所选行的数量. 问题是当用户选择多行时,SelCount返回0.如果手动填充列表(即不通过OnData事件),这可以正常工作. 有任何想法吗? 谢谢 我需要启用或禁用按钮,具体取决于列表中是否至少选择了一行.

以下是重现此问题的代码.使用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;interfaceuses  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  endend
解决方法 根本问题是当您SHIFT单击多个项目时,您将不会获得已选择的项目的任何OnSelectItem事件. SHIFT Click会首先取消选择所有列表视图项,在新项目被选中之前触发Item = nil和Selected = False的单个OnSelectItem事件.在该事件发生时,TListVIEw.SelCount确实为0,因此您禁用了按钮,但是没有进一步的OnSelectItem事件告诉您已经选择了新项目,因此您不再检查SelCount以重新启用按钮.

当单个项目在选定和未选定之间更改状态时,或者当整个ListVIEw中的所有项目更改为相同的选定/未选定状态时,将触发OnSelectItem事件以回复LVN_ITEMCHANGED通知.但是,在虚拟模式下,当多个连续项目同时更改为相同的状态时,windows可以为该项目范围发送单个LVN_ODSTATECHANGED通知. TListLIEw在收到LVN_ODSTATECHANGED时不触发OnSelectItem,而是触发OnDataStateChange,例如:

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的更新.

总结

以上是内存溢出为你收集整理的delphi – TListView SelCount报告虚拟列表中错误的项目数全部内容,希望文章能够帮你解决delphi – TListView SelCount报告虚拟列表中错误的项目数所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1273476.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-08
下一篇2022-06-08

发表评论

登录后才能评论

评论列表(0条)

    保存