2017-10-14 17 views
1

Delphi 10.2 TokyoのTListBoxとTListBoxItemでわからないことがあります。ListBoxItem Visible Error

一部の値(TListBoxItem)は、リストボックスにロードされます。最初の文字が変更されたときにTListBoxGroupHeaderが追加されます。

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のコンテンツが含まれている場合は、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

@Victoriaは答えてくれてありがとうございました。私は自分のTRecangleを作成するTVertScrollBoxとTLayoutで独自のメニューを作成することにしました。それは仕事です。私は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;