我在Delphi 10.2 Tokyo的TListBox和TListBoxItem中无法理解。
有些值(TListBoxItem)被加载到我的ListBox,当第一个字母改变时我添加了一个TListBoxGroupHeader。
public class Program
{
public static void Main(string[] args)
{
var services = new ServiceCollection()
.AddLogging(config => config.AddConsole())
.BuildServiceProvider();
services.GetRequiredService<ILogger<Program>>()
.LogCritical("Hello");
((IDisposable) services)?.Dispose();
}
}
我使用TEdit在此ListBox中搜索。我在这里遇到了问题。如果ListBoxItem包含Edit I设置为Visible为True的内容,则我将其设置为False。
procedure TForm1.Button1Click(Sender: TObject);
var
lbItem: TListBoxItem;
Letter: string;
ListBoxGroupHeader: TListBoxGroupHeader;
i: integer;
ListValue: TStringList;
begin
Letter := '';
ListValue := TStringList.Create;
try
ListValue.Add('Germany');
ListValue.Add('Georgie');
ListValue.Add('France');
ListValue.Add('Venezuela');
ListValue.Add('Poland');
ListValue.Add('Russia');
ListValue.Add('Sweden');
ListValue.Add('Denmark');
ListBox1.BeginUpdate;
for i := 0 to ListValue.Count - 1 do
begin
if Letter <> Copy(ListValue[i], 0, 1).ToUpper then
begin
ListBoxGroupHeader := TListBoxGroupHeader.Create(ListBox1);
ListBoxGroupHeader.Text := Copy(ListValue[i], 0, 1).ToUpper;
ListBox1.AddObject(ListBoxGroupHeader);
end;
lbItem := TListBoxItem.Create(ListBox1);
lbItem.Text := ListValue[i];
lbItem.Tag := i;
ListBox1.AddObject(lbItem);
Letter := Copy(ListValue[i], 0, 1).ToUpper;
end;
finally
ListBox1.EndUpdate;
FreeAndNil(ListValue);
end;
end;
第一个GroupHeader(字母G)始终可见!并且看起来GroupHeader后面有一个ListBoxItem ..当我使用检查点时,Visible设置为false ..所以我不明白..
如果我写信#34; V&#34;我只看到GroupHeader的字母&#34; G&#34;。
如果它是GroupHeader,我会尝试更改文本值。
procedure TForm1.Edit1ChangeTracking(Sender: TObject);
var
i : integer;
ListBoxItem: TListBoxItem;
begin
ListBox1.BeginUpdate;
try
for i := 0 to ListBox1.Items.Count - 1 do
begin
if ListBox1.ListItems[i] is TListBoxItem then
begin
ListBoxItem := TListBoxItem(ListBox1.ListItems[i]);
if Edit1.Text.Trim = '' then
begin
ListBoxItem.Visible := True
end
else
begin
if ListBox1.ListItems[i] is TListBoxGroupHeader then
ListBoxItem.Visible := False
else
ListBoxItem.Visible := ListBoxItem.Text.ToLower.Contains(Edit1.Text.Trim.ToLower);
end;
end;
end;
finally
ListBox1.EndUpdate;
end;
end;
这是改变文本而不是第一个GroupHeader(字母G)......
不知道我是否使用它不好,或者它是否是一个错误?
答案 0 :(得分:1)
我可以重现你所描述的内容,它与隐藏标题有关,同时保持标题下的项目可见。在这种情况下,应用程序显示标题而不是项目。我还没有检查过里面的错误,但似乎不是你想要的。恕我直言,你想保持与搜索文本相匹配的可见项目及其各自的标题,并且只隐藏没有项目的标题。
如果是这样,试试这个:
procedure FilterItems(const Text: string; ListBox: TListBox);
var
I: Integer; { ← loop variable }
Hide: Boolean; { ← flag indicating if we want to hide the last header we passed }
Item: TListBoxItem; { ← currently iterated item }
Head: TListBoxGroupHeader; { ← last header item we passed during iteration }
begin
Head := nil;
Hide := True;
ListBox.BeginUpdate;
try
{ if search text is empty, show all items }
if Text.IsEmpty then
for I := 0 to ListBox.Content.ControlsCount - 1 do
ListBox.ListItems[I].Visible := True
else
{ otherwise compare text in non header items }
begin
for I := 0 to ListBox.Content.ControlsCount - 1 do
begin
Item := ListBox.ListItems[I];
{ if the iterated item is header }
if Item is TListBoxGroupHeader then
begin
{ set the previous header visibility by at least one visible item }
if Assigned(Head) then
Head.Visible := not Hide;
{ assume hiding this header and store its reference }
Hide := True;
Head := TListBoxGroupHeader(Item);
end
else
{ if the iterated item is a regular item }
if Item is TListBoxItem then
begin
{ set the item visibility by matching text; if the item remains visible, it
means we don't want to hide the header, so set our flag variable as well }
if Item.Text.ToLower.Contains(Text) then
begin
Hide := False;
Item.Visible := True;
end
else
Item.Visible := False;
end;
end;
{ the iteration finished, so now setup visibility of the last header we passed }
if Assigned(Head) then
Head.Visible := not Hide;
end;
finally
ListBox.EndUpdate;
end;
end;
procedure TForm1.Edit1ChangeTracking(Sender: TObject);
begin
FilterItems(Edit1.Text.Trim.ToLower, ListBox1);
end;