2017-10-14 1 views
1

TListBox 및 TListBoxItem을 사용하여 Delphi 10.2 Tokyo에서 이해할 수없는 부분이 있습니다.ListBoxItem 보이는 오류

첫 번째 문자를 변경하면 TListBoxGroupHeader가 추가 될 때 일부 값 (TListBoxItem)이 내 ListBox에로드됩니다.

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; 

이 ListBox에서 검색하려면 TEdit을 사용합니다. 여기에 내가 문제가있다. ListBoxItem에 Edit I의 내용이 들어있는 경우 Visible을 True로 설정하고 그렇지 않으면 False로 설정합니다.

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)는 항상 표시됩니다. GroupHeader 뒤에 ListBoxItem이있는 것처럼 보입니다. 체크 포인트를 사용할 때 Visible은 false로 설정되어 있습니다 .. 이해할 수 없었습니다 ..

글자 "V"를 쓰면 GroupHeader 만 표시됩니다. 문자 "G".

GroupHeader 인 경우 텍스트 값을 변경하려고합니다.

if ListBox1.ListItems[i] is TListBoxGroupHeader then 
    ListBoxItem.Text := '>>' + ListBoxItem.Text + '<<' 

그게 전부 변경 텍스트가 아닌 첫 GroupHeader (편지 G)에 대한이 ... 내가 나쁜 사용하는 경우

알고하지 마십시오, 또는 버그가 있다면?

+0

예. 버그가 있습니다 (항목 표시 설정시). 어쨌든, 나는 이것이 당신이 원하는 것을 생각하지 않습니다. 난 당신이 국가를 검색하고 비 머리말 항목에서 검색이 필요없는 해당 항목이없는 머리글을 숨길 해당 머리글과 일치하는 텍스트 만 표시하려고한다고 생각합니다. 그것이 당신이 달성하기를 원하는 것입니까? – Victoria

+0

@ 빅토리아는 대답을 주셔서 감사합니다. TVetScrollBox와 TLayout을 사용하여 내 TRecangle을 만드는 고유 한 메뉴를 만들기로 결정했습니다. 그 일을 수행하면서 Embarcadero의 버그 추적기에서 작업을 생성합니다. – Bosshoss

답변

1

설명해 주신 내용을 재현 할 수 있으며 해당 헤더 아래에 항목을 보관하는 동안 헤더 숨기기와 관련이 있습니다. 이 경우 응용 프로그램은 항목이 아니라 머리글을 표시합니다. 나는 내부에서 무엇이 잘못되었는지 확인하지 않았지만 그것이 당신이 원하는 것이 아닌 것처럼 보입니다. IMHO 검색 텍스트와 일치하는 보이는 항목을 해당 머리글과 함께 유지하고 항목이없는 머리글 만 숨기려고합니다.

그 그렇다면,이 시도 :

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;