7

リストで少なくとも行が選択されているかどうかに応じて、ボタンを有効または無効にする必要があります。

以下は、この問題を再現するためのコードです。リストは OnData イベントを使用して設定され、複数の行を選択できます。

OnSelectItem を使用してユーザーが選択を変更したことを検出し、TListView SelCount 関数を使用して選択された行の数を検出できると考えました。

問題は、ユーザーが複数の行を選択すると、SelCount が 0 を返すことです。リストが手動で入力されている場合 (つまり、OnData イベントを使用していない場合)、これは正常に機能します。

何か案は?

ありがとう

更新: 代わりに OnChange イベントを使用するとうまくいくようです。それでも、(SelectItem イベント内から) 複数の行が選択されたときに SelCount が 0 を返す理由を理解することは興味深いでしょう。

別の更新: テスト プロジェクトを投稿しました: https://dl.dropboxusercontent.com/u/35370420/TestListView2.zipとスクリーンショット:

ここに画像の説明を入力

この問題を再現するには、アプリを実行して Item1 を選択し、Shift キーを押しながら Item2 をクリックします。ボタンは無効です。私の意図は、リストで少なくとも 1 つの項目が選択されている限り、ボタンを動的に有効にすることでした。選択された項目がない場合、ボタンは無効になります。

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
4

1 に答える 1

5

根本的な問題は、SHIFT+Click複数のアイテムをOnSelectItem選択すると、選択されたアイテムのイベントが発生しないことです。はSHIFT+Click、最初にすべてのリスト ビュー アイテムの選択を解除し、新しいアイテムが選択される前にとで 1 つのOnSelectItemイベントをトリガーします。そのイベントの時点で は実際には 0 であるため、ボタンを無効にしますが、新しい項目が選択されたことを通知するイベントがそれ以上ないため、ボタンを再度有効にするために再度チェックすることはありません。Item=nilSelected=FalseTListView.SelCountOnSelectItemSelCount

このイベントは、1 つの項目の状態が選択状態と非選択状態の間で変化したとき、または ListView 全体のすべての項目が同じ選択状態/非選択状態に変化したときOnSelectItemに、通知に応答してトリガーされます。LVN_ITEMCHANGEDただし、仮想モードでは、連続する複数のアイテムが同時に同じ状態に変化した場合、Windows は代わりに、LVN_ODSTATECHANGEDその範囲のアイテムに対して 1 つの通知を送信できます。 を受信TListLiewして​​もトリガーしません。代わりにトリガーします。例:OnSelectItemLVN_ODSTATECHANGEDOnDataStateChange

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最善の解決策は、個々のアイテムの状態変更を手動で有効/無効にしないことです。フォームに をドロップしTActionManager、新しい を作成してプロパティにTAction割り当て、イベントを使用して現在の に基づいてを有効/無効にします。例:TButton.ActionTAction.OnUpdateTActionTListView.SelCount

procedure TForm3.MyActionUpdate(Sender: TObject);
begin
  MyAction.Enabled := ListView1.SelCount > 0;
end;

TButtonこれにより、ListView 通知メッセージが処理された後など、メイン メッセージ キューがアイドル状態になるたびに、関連付けられた が自動的に有効/無効になります。このようにして、TButtonListView アイテムの選択/選択解除に使用される入力の組み合わせに関係なく、更新を維持できます。

于 2014-03-07T20:05:25.990 に答える