- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
简短版本:有没有办法单独控制或修改LisBox项目?例如,分别将其 Visible 属性设置为 False。我在搜索时在Fire Monkey中发现了TListBoxItem类,但我不想使用Fire Monkey并希望在VCL中使用它。
详细版本:我尝试使用两个 TStringList 和一个 Edit 来过滤我的 ListBox,一个 StringList 是全局的以保留原始列表 (list_files_global
),另一个 StringList 来帮助过滤过程 (list_files_filter
) 和我的主要文件列表是我的列表框 (list_files
)。当程序开始存储我的原始列表时,我在 onCreate
事件上创建了全局 StringList:
procedure Tfrm_main.FormCreate(Sender: TObject);
Begin
list_files_global := TStringList.Create;
list_files_global.Assign(list_files.Items);
End;
并使用Edit的onChange
事件进行过滤:
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;
要关闭过滤器,只需从我最初创建的全局列表中恢复列表:
list_files.Items := list_files_global;
到目前为止,一切正常,但问题是当我尝试从过滤列表中编辑/重命名/删除项目时,例如我更改一个项目:
list_files.Items[i] := '-- Changed Item --';
列表将被编辑,但是当我关闭过滤器时,原始列表将返回并且所有更改都会丢失。所以我想知道有没有什么正确的方法可以解决这个问题?比如单独隐藏项目或更改项目可见性等...所以我可以更改过滤算法并摆脱所有这些制作额外的列表。我在网上查了一天,也查了Delphi的帮助文件,没有找到有用的信息。
最佳答案
这是我经常做的事情,但是使用 ListView 而不是列表框。但基本原理是相同的。
我倾向于将各个项目存储为对象,这些对象是 Delphi 中的引用类型。我将它们全部保存在一个未过滤的主列表中,该列表拥有这些对象,同时我维护一个过滤列表(不拥有这些对象)用于显示目的。像@Sertac一样,我将其与虚拟 ListView 结合起来。
要了解其实际工作原理,请创建一个新的 VCL 应用程序并在主窗体上放置一个 ListView (lvDisplay
) 和一个编辑控件 (eFilter
):
注意,我已向 ListView 控件添加了三列:“姓名”、“年龄”和“颜色”。我还将其设为虚拟 (OwnerData = True
)。
现在定义各个数据项的类:
type
TDogInfo = class
Name: string;
Age: Integer;
Color: string;
constructor Create(const AName: string; AAge: Integer; const AColor: string);
function Matches(const AText: string): Boolean;
end;
哪里
{ TDogInfo }
constructor TDogInfo.Create(const AName: string; AAge: Integer;
const AColor: string);
begin
Name := AName;
Age := AAge;
Color := AColor;
end;
function TDogInfo.Matches(const AText: string): Boolean;
begin
Result := ContainsText(Name, AText) or ContainsText(Age.ToString, AText) or
ContainsText(Color, AText);
end;
让我们创建未经过滤的狗列表:
TForm1 = class(TForm)
eFilter: TEdit;
lvDisplay: TListView;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FList, FFilteredList: TObjectList<TDogInfo>;
public
end;
哪里
function GetRandomDogName: string;
const
DogNames: array[0..5] of string = ('Buster', 'Fido', 'Pluto', 'Spot', 'Bill', 'Rover');
begin
Result := DogNames[Random(Length(DogNames))];
end;
function GetRandomDogColor: string;
const
DogColors: array[0..2] of string = ('Brown', 'Grey', 'Black');
begin
Result := DogColors[Random(Length(DogColors))];
end;
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
FList := TObjectList<TDogInfo>.Create(True); // Owns the objects
// Populate with sample data
for i := 1 to 1000 do
FList.Add(
TDogInfo.Create(GetRandomDogName, Random(15), GetRandomDogColor)
);
FFilteredList := FList;
lvDisplay.Items.Count := FFilteredList.Count;
lvDisplay.Invalidate;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if FFilteredList <> FList then
FreeAndNil(FFilteredList);
FreeAndNil(FList);
end;
这个想法是 ListView 控件始终显示FFilteredList
,它要么指向与FList
相同的对象实例,要么指向过滤(或排序)的对象实例版本:
// The list view's OnData event handler
procedure TForm1.lvDisplayData(Sender: TObject; Item: TListItem);
begin
if FFilteredList = nil then
Exit;
if not InRange(Item.Index, 0, FFilteredList.Count - 1) then
Exit;
Item.Caption := FFilteredList[Item.Index].Name;
Item.SubItems.Add(FFilteredList[Item.Index].Age.ToString);
Item.SubItems.Add(FFilteredList[Item.Index].Color);
end;
// The edit control's OnChange handler
procedure TForm1.eFilterChange(Sender: TObject);
var
i: Integer;
begin
if string(eFilter.Text).IsEmpty then // no filter, display all items
begin
if FFilteredList <> FList then
begin
FreeAndNil(FFilteredList);
FFilteredList := FList;
end;
end
else
begin
if (FFilteredList = nil) or (FFilteredList = FList) then
FFilteredList := TObjectList<TDogInfo>.Create(False); // doesn't own the objects
FFilteredList.Clear;
for i := 0 to FList.Count - 1 do
if FList[i].Matches(eFilter.Text) then
FFilteredList.Add(FList[i]);
end;
lvDisplay.Items.Count := FFilteredList.Count;
lvDisplay.Invalidate;
end;
结果:
请注意,每只狗始终只有一个内存中对象,因此如果您重命名一只狗,更改将反射(reflect)在 ListView 中,无论是否经过过滤。 (但不要忘记使其无效!)
关于delphi - 按字符串过滤时隐藏 TListBox 中的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58068080/
我正在使用 Delphi XE4,下面是我的示例应用程序。 unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.S
如果您的列表框包含许多项目并且您需要选择例如项目,则项目的选择会变得很痛苦。通过手动单击和选择 400 个项目。 有没有一种优雅的方法可以使用某个“ 通过模式函数 选择项目”从列表框中选择项目? 最佳
我在我的数据库中用 MYDAC 组件创建了一个表并添加了数据。我如何从该表中提取列中的这些值? 我试过了,但没用; MyQuery1.Close; MyQuery1.SQL.Text :='SEL
当选择一个项目(按住鼠标左键)并将鼠标移到列表框之外时,我需要更改列表框滚动的速度。要复制该行为,请执行以下操作: 将列表框拖放到表单上(+- 250 x 200 奇数)。不要让它太大,否则滚动条在底
我一直在尝试使用 TListBox 控件、绘制图像和更改字体样式等。我想稍微加强一下,并尝试通过缩进和多级缩进来更多地操作项目。 看看这张图片以获得更好的想法: 这个想法是列表中位于起始项和结束项之间
我在 Delphi 中为 TListBox 有一个自定义 style,我可以在其中简单地更改 Text 属性喜欢 lb_item.StylesData['location'] := 'New Text
我正在使用 TListBox 组件来显示带有 CheckBoxes 的列表。 它在 iOS 上运行良好,但在 Android 上滚动时会产生小的延迟。 乍一看,我认为这是因为每个 TListBoxIt
我有一个TListBox,每个项目都有控件,例如TEdit、TComboBox、TSwitch等, 右对齐。此列表中有大约 20 项,因此它超出了屏幕,因此用户需要滚动(通过滑动手指)才能到达底部。
我想通过将列表框与其他两个列表框进行比较来清理列表框。 Listbox1 将包含项目的大列表 Listbox2 会有我想从 listbox1 中删除的词 Listbox3 将包含必须存在的强制性单词才
我正在 Lazarus 上开发一个电子书管理器,但我在使用一个我从未使用过的组件 (TListBox) 时遇到了一些麻烦。在名为 CategoryList 的 TListBox 上,我有这些项目: L
我正在使用 XE7 和 FMX。 我的问题是 TListbox 的 OnChange-Event 无法正确处理多选(它不会在每次发生更改时触发)。 重现步骤: 创建一个 FMX 应用程序并将 TLis
我正在创建一个多设备 FireMonkey 应用程序,我想在选择 TListBox 项目时更改其颜色。 如何在 Rad Studio XE7 中完成此操作? 最佳答案 打开位图样式设计器(请参阅 RA
查看代码: function ShowItem(MyData: TMyData): TListItem; var vListItem: TListItem; begin vListItem :
我有一种记录类型。我想在 TListbox 中添加该记录类型的变量,并在 TListbox 的单击事件上检索它。是否可以?如果是的话怎么办? 我使用添加它 lstbox.AddItem(data,my
我正在将 ListBox.Style := lbOwnerDrawFixed 与 OnDrawItem 一起使用: procedure TForm1.ListBox1DrawItem(Control:
简短版本:有没有办法单独控制或修改LisBox项目?例如,分别将其 Visible 属性设置为 False。我在搜索时在Fire Monkey中发现了TListBoxItem类,但我不想使用Fire
是否有使用 TListBox 获得“OnChange”类型功能的技巧?我可以对组件进行子类化并添加属性等,然后仅在索引更改时执行 OnClick 代码...我还可以使用表单级别变量来破解它以存储当前索
procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwner
在 DelphiXE 中,我使用 tFileOpenDialog 选择一个文件夹,然后在 tListBox 中列出该文件夹中的所有 *.jpg 文件。我允许将列表项拖放到列表中进行自定义排序,以便稍后
这就是我从本地服务器上的列表中获取一些项目的方法。 我认为它仍然需要一些重构(抱歉,我是 Delphi 的初学者),但是我想更好地理解为什么 ListItem colors 没有被改变。 我做了一些调
我是一名优秀的程序员,十分优秀!