在按字符串过滤时隐藏TListBox中的项目 [英] Hiding items in TListBox while filtering by String

查看:77
本文介绍了在按字符串过滤时隐藏TListBox中的项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

短版:是否可以单独控制或修改LisBox项目?例如,将其 Visible 属性分别设置为False。
我在搜索时在 Fire Monkey 中找到了 TListBoxItem 类,但是我不想使用Fire Monkey并希望在VCL中使用它。



详细版本
我试图使用两个TStringList和一个Edit过滤ListBox,其中一个StringList是全局的,以保留原始列表( list_files_global )和另一个StringList来帮助过滤过程( list_files_filter ),而我的主要文件列表是我的ListBox( list_files )。
我在程序开始存储原始列表时在 onCreate 事件上创建了全局StringList:

 程序Tfrm_main.FormCreate(Sender:TObject); 
开始
list_files_global:= TStringList.Create;
list_files_global.Assign(list_files.Items);
结束;

,并使用Edit的 onChange 事件进行过滤:

 过程Tfrm_main.edit_files_filterChange(Sender:TObject); 
Var
list_files_filter:TStringList;
i:整数;
开始
list_files_filter:= TStringList.Create;
list_files_filter.Assign(list_files.Items);

list_files.clear;

for i:= 0到list_files_filter.Count-如果pos(edit_files_filter.text,list_files_filter [i])> 1则
0然后
list_files.Items.Add(list_files_filter [i]);

结束;

要关闭过滤器,只需从我最初创建的全局列表中恢复列表即可:

  list_files.Items:= list_files_global; 

到目前为止,一切正常,但是问题是当我尝试编辑/重命名时/从过滤列表中删除项目,例如,我更改了一个项目:

  list_files.Items [i]:='-已更改项目-'; 

列表将被编辑,但是当我关闭过滤器时,原始列表将返回并且所有更改丢失。
,所以我想知道是否有解决此问题的适当方法?诸如单独隐藏项目或更改项目可见性等之类的东西,因此我可以更改过滤算法并摆脱所有多余的列表。
我在互联网上搜索了整整一天,没有任何有用的信息。

解决方案

API中的列表框 ,没有任何可见性属性。不显示项目的唯一选择是删除项目。



但是,您可以在虚拟模式下使用控件,因为根本没有项目。您决定要保留什么数据,要显示什么。那是 LBS_NODATA 窗口样式。在VCL中,将 style 属性设置为 lbVirtual



以下是极为简化的示例。



让我们保留一组记录,每个虚拟项目一条记录。

  type 
TListItem =记录
FileName:字符串;
可见:布尔值;
结尾;

TListItems = TListItem的数组;

您可以根据需要扩展字段。我补充说,可见度是该问题的主要关注之一。您可能会添加代表原始名称的内容,以便知道已更改的名称,等等。



每个列表框具有一个数组。本示例包含一个列表框。

  var 
ListItems:TListItems;

最好将其设置为字段,这仅用于演示。



 使用
ioutils,类型;

在创建表单时进行了一些初始化。清空过滤器编辑。相应地设置列表框样式。填写一些文件名。所有项目将在启动时可见。

 过程TForm1.FormCreate(Sender:TObject); 
var
ListFiles:TStringDynArray;
i:整数;
开始
ListFiles:= ioutils.TDirectory.GetFiles(TDirectory.GetCurrentDirectory);

SetLength(ListItems,Length(ListFiles));
for i:= 0到High(ListItems)确实开始
ListItems [i] .FileName:= ListFiles [i];
ListItems [i] .Visible:= True;
结尾;

ListBox1.Style:= lbVirtual;
ListBox1.Count:=长度(ListFiles);

Edit1.Text:=’;;
结尾;

在虚拟模式下,列表框仅对 Count 属性。



这里是过滤器部分,区分大小写。

 程序TForm1.Edit1Change(Sender:TObject); 
var
文本:字符串;
Cnt:整数;
i:整数;
开始
文本:= Edit1.Text;
如果Text =’,则以
for i:= 0到High(ListItems)开始
ListItems [i]。可见:= True;
Cnt:=长度(ListItems);
结束,否则开始
Cnt:= 0;
for i:= 0到High(ListItems)确实开始
ListItems [i]。可见:= Pos(Text,ListItems [i] .FileName)> 0;
如果ListItems [i]。可见,则
Inc(Cnt);
结尾;
结尾;
ListBox1.Count:= Cnt;
结尾;

编辑中 OnChange 的特殊情况是当文本为空时。然后所有项目都会显示。否则,代码来自问题。在这里,我们还保留可见项的总数,以便我们可以相应地更新列表框。



现在,唯一有趣的部分是列表框需要数据。

 过程TForm1.ListBox1Data(Control:TWinControl; Index:Integer; 
var Data:string);
var
VisibleIndex:整数;
i:整数;
开始
VisibleIndex:= -1;
for i:= 0到High(ListItems)如果ListItems [i]确实以
开始。可见然后
Inc(VisibleIndex);
(如果VisibleIndex =索引),然后开始
数据:= ListItems [i] .FileName;
休息时间;
结尾;
结尾;
结尾;

这里发生的情况是,列表框要求显示一个提供其索引的项目。我们遍历主列表,对可见项进行计数,以找出与该索引匹配的项,并提供其文本。


Short Version: Is there any way to control or modify LisBox items individually? for example set their Visible property to False separately. I found a TListBoxItem class in Fire Monkey when I was searching, but I don't want to use Fire Monkey and want it in VCL.

Detailed Version: I tried to filter my ListBox using two TStringList and an Edit, one StringList is global to keep the original list (list_files_global) and another StringList to help filtering procedure (list_files_filter) and my primary list of files is my ListBox (list_files). I created my global StringList on onCreate event while program is starting to store my original list:

procedure Tfrm_main.FormCreate(Sender: TObject);
Begin
  list_files_global := TStringList.Create;
  list_files_global.Assign(list_files.Items);
End;

and used Edit's onChange event for filtering:

procedure Tfrm_main.edit_files_filterChange(Sender: TObject);
Var
  list_files_filter: TStringList;
  i: Integer;
Begin
  list_files_filter := TStringList.Create;
  list_files_filter.Assign(list_files.Items);

  list_files.Clear;

  for i := 0 to list_files_filter.Count - 1 do 
    if pos(edit_files_filter.text, list_files_filter[i]) > 0 then 
      list_files.Items.Add(list_files_filter[i]);

End;

and for switching off the filter, just recover the list from my global list that I created at first:

list_files.Items := list_files_global;

here so far, everything works just fine, but problem is when I'm trying to edit/rename/delete items from filtered list, for example I change an item:

list_files.Items[i] := '-- Changed Item --';

list will be edited, but when I switch off the filter, the original list will be back and all changes are lost. so I want to know is there any proper way to solve this problem? Something like hiding items individually or change items visibility, etc... so I can change the filtering algorithm and get rid of all this making extra lists. I searched the internet and looked into Delphi's help file for a whole day and nothing useful came up.

解决方案

The items of a VCL listbox, List Box in the API, does not have any visibility property. The only option for not showing an item is to delete it.

You can use the control in virtual mode however, where there are no items at all. You decide what data to keep, what to display. That's LBS_NODATA window style in the API. In VCL, set the style property to lbVirtual.

Extremely simplified example follows.

Let's keep an array of records, one record per virtual item.

type
  TListItem = record
    FileName: string;
    Visible: Boolean;
  end;

  TListItems = array of TListItem;

You can extend the fields as per your requirements. Visibility is one of the main concerns in the question, I added that. You'd probably add something that represents the original name so that you know what name have been changed, etc..

Have one array per listbox. This example contains one listbox.

var
  ListItems: TListItems;

Better make it a field though, this is for demonstration only.

Required units.

uses
  ioutils, types;

Some initialization at form creation. Empty the filter edit. Set listbox style accordingly. Fill up some file names. All items will be visible at startup.

procedure TForm1.FormCreate(Sender: TObject);
var
  ListFiles: TStringDynArray;
  i: Integer;
begin
  ListFiles := ioutils.TDirectory.GetFiles(TDirectory.GetCurrentDirectory);

  SetLength(ListItems, Length(ListFiles));
  for i := 0 to High(ListItems) do begin
    ListItems[i].FileName := ListFiles[i];
    ListItems[i].Visible := True;
  end;

  ListBox1.Style := lbVirtual;
  ListBox1.Count := Length(ListFiles);

  Edit1.Text := '';
end;

In virtual mode the listbox is only interested in the Count property. That will arrange how many items will show, accordingly the scrollable area.

Here's the filter part, this is case sensitive.

procedure TForm1.Edit1Change(Sender: TObject);
var
  Text: string;
  Cnt: Integer;
  i: Integer;
begin
  Text := Edit1.Text;
  if Text = '' then begin
    for i := 0 to High(ListItems) do
      ListItems[i].Visible := True;
    Cnt := Length(ListItems);
  end else begin
    Cnt := 0;
    for i := 0 to High(ListItems) do begin
      ListItems[i].Visible := Pos(Text, ListItems[i].FileName) > 0;
      if ListItems[i].Visible then
        Inc(Cnt);
    end;
  end;
  ListBox1.Count := Cnt;
end;

The special case in the edit's OnChange is that when the text is empty. Then all items will show. Otherwise code is from the question. Here we also keep the total number of visible items, so that we can update the listbox accordingly.

Now the only interesting part, listbox demands data.

procedure TForm1.ListBox1Data(Control: TWinControl; Index: Integer;
  var Data: string);
var
  VisibleIndex: Integer;
  i: Integer;
begin
  VisibleIndex := -1;
  for i := 0 to High(ListItems) do begin
    if ListItems[i].Visible then
      Inc(VisibleIndex);
    if VisibleIndex = Index then begin
      Data := ListItems[i].FileName;
      Break;
    end;
  end;
end;

What happens here is that the listbox requires an item to show providing its index. We loop through the master list counting visible items to find out which one matches that index, and supply its text.

这篇关于在按字符串过滤时隐藏TListBox中的项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆