【问题标题】:Filter a multiple column listview过滤多列列表视图
【发布时间】:2012-07-28 13:58:37
【问题描述】:

以下代码将根据在TEdit 控件中键入的内容过滤TListView 控件的项目,如果 ListView 由单列组成,它可以正常工作,但是如果您有超过 1 列,然后在应用过滤器时其他列中的项目被破坏,所以我希望有人可能知道需要在下面的代码中添加什么以在过滤 ListView 时保留这些列。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, strutils, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    Edit1: TEdit;
    procedure Edit1Change(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  StrList : TStringList;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
   Index : Integer;
begin
     StrList := TStringList.Create;
     for Index := 0 to ListView1.Items.Count -1 do
        StrList.Add(ListView1.Items[Index].Caption);
end;
procedure TForm1.Edit1Change(Sender: TObject);
var
   Index : Integer;
begin
   ListView1.Clear;
   for Index := 0 to StrList.Count - 1 do
     if Pos(Edit1.Text, StrList.Strings[Index]) > 0 then
        ListView1.AddItem(StrList.Strings[Index], nil);
   if Edit1.Text = '' then
     for Index := 0 to StrList.Count - 1 do
       ListView1.AddItem(StrList.Strings[Index], nil);
end;


end.

【问题讨论】:

  • 听起来不像想要一个行过滤器,因为它显然包含或排除了该行。如果它不匹配,看起来你只想在单元格中粘贴一个空白值。如果没有列匹配,也许不要添加行...
  • 或者也许你可以测试每一列,如果其中任何一个匹配添加行,他想了一会儿说。更好的是,您将行中的数据和过滤器传递给布尔函数,如果为真则添加,这将是一种更自然的方法。
  • 抱歉,我不太听从您的回复。请您再次尝试改写一下。感谢您的回复顺便说一句。我要做的就是创建一个过滤器,就像您使用 DBgrid 一样,但我只是使用 ListView 和编辑控件,而不是带有 Dataset 的网格。
  • 嗯?您说“其他列中的项目被破坏”。当然是,您过滤掉了行,这也是 DBGrid 过滤器的工作原理。

标签: delphi listview filter


【解决方案1】:

您正在清除列表视图,然后在没有 SubItems 的情况下添加到其 Items - 这就是其他列为空的原因。

要过滤列表视图的内容,使用virtual mode 中的列表视图可能更容易,您可以在其中设置计数并在回调中按需提供数据。这是一个简单的例子:

形式:

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 282
  ClientWidth = 418
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object ListView1: TListView
    Left = 8
    Top = 39
    Width = 402
    Height = 235
    Columns = <
      item
        Caption = 'Name'
        Width = 80
      end
      item
        Caption = 'Title'
        Width = 160
      end
      item
        Alignment = taRightJustify
        Caption = 'Age'
        Width = 80
      end>
    OwnerData = True
    SortType = stText
    TabOrder = 0
    ViewStyle = vsReport
    OnData = ListView1Data
  end
  object Edit1: TEdit
    Left = 8
    Top = 12
    Width = 121
    Height = 21
    TabOrder = 1
    OnChange = Edit1Change
  end
end

代码:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, System.Contnrs,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Grids, Vcl.ComCtrls;

type
  TDataItem = class
  private
    FAge: Integer;
    FFirstName: string;
    FLastName: string;
  public
    property Age: Integer read FAge;
    property FirstName: string read FFirstName;
    property LastName: string read FLastName;
  end;

  TForm1 = class(TForm)
    ListView1: TListView;
    Edit1: TEdit;
    procedure ListView1Data(Sender: TObject; Item: TListItem);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
  private
    FActiveItems: TList;
    FItems: TObjectList;
    procedure AddTestData;
    procedure ApplyFilter(const S: string = '');
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.AddTestData;
  procedure AddDataItem(const FirstName, LastName: string; Age: Integer);
  var
    DataItem: TDataItem;
  begin
    DataItem := TDataItem.Create;
    try
      DataItem.FFirstName := FirstName;
      DataItem.FLastName := LastName;
      DataItem.FAge := Age;
      FItems.Add(DataItem);
    except
      DataItem.Free;
      raise;
    end;
  end;
begin
  AddDataItem('John', 'Doe', 26);
  AddDataItem('Jane', 'Warwick', 29);
  AddDataItem('Stephen', 'Marley', 33);
  AddDataItem('Alice', 'Connoly', 48);
  AddDataItem('Adam', 'Spears', 63);
end;

procedure TForm1.ApplyFilter(const S: string);
var
  I: Integer;
begin
  ListView1.Items.BeginUpdate;
  try
    ListView1.Clear;
    FActiveItems.Clear;
    for I := 0 to FItems.Count - 1 do
      if (S = '') or (Pos(UpperCase(S), UpperCase(TDataItem(FItems[I]).FirstName)) <> 0) then
        FActiveItems.Add(FItems[I]);
    ListView1.Items.Count := FActiveItems.Count;
  finally
    ListView1.Items.EndUpdate;
  end;
end;

procedure TForm1.Edit1Change(Sender: TObject);
begin
  ApplyFilter((Sender as TEdit).Text);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FItems := TObjectList.Create;
  FActiveItems := TList.Create;
  AddTestData;
  ApplyFilter(Edit1.Text);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FActiveItems.Free;
  FItems.Free;
end;

procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
var
  DataItem: TDataItem;
begin
  DataItem := FActiveItems[Item.Index];
  Item.Caption := DataItem.FirstName;
  Item.SubItems.Add(DataItem.LastName);
  Item.SubItems.Add(IntToStr(DataItem.Age));
end;

end.

【讨论】:

  • 谢谢,经过一番折腾,我能够使用数据库中的信息使其工作。
猜你喜欢
  • 2022-11-29
  • 2017-06-26
  • 1970-01-01
  • 2012-05-28
  • 2013-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多