Filtrování Virtual Tree View

vložil Radek Červinka 24. října 2012 22:36

Moc se mi líbí způsob vyhledávání ala Windows 7 nebo novější Delphi IDE, tj. začnete psát a zobrazují se vám jen relevantní záznamy. Přemýšlel jsem, jak je to těžké udělat pro můj milovaný švýcarský nůž mezi komponentami aka TVirtualTreeView. Jelikož právě v Delphi IDE je použit modifikovaný VirtualTreeView tak jsem doufal, že to až takový problém nebude. A nebyl.

Virtual TreeView

Předpokládám, že máte přečteny minulé díly seriálu o VT - jsou dostupné přes tag na konci článku.

Uzel stromu (tedy PVirtualNode) má kromě jiných možných stavů i stav vsFiltered, který se nastavuje a (nejlépe) zjišťuje přes property stromu IsFiltered … a to je v podstatě vše - zbytek zařídí VT.

Následující kód rekurzivně projde strom a nechá zobrazené jen ty uzly, co obsahují filtr (na obrázku jen s "zá"). Je to část většího kódu a nechtěl jsem to moc upravovat - proto se některé části dají napsat kratší.

PVTNavigatorRec je v mém případě record obsahující virtuální data - viz minulé díly. U vás to bude něco jiného.

Volání (vt je strom) je pak:

  mUpdateFilter(vt.RootNode, AnsiUppercase(Trim(edtSearch.Text)));

Jen bych upozornil na řádek 41 a 45, kdy v prvním případě je porovnání, v druhém pak zajištění, že celá cesta k uzlu bude rozbalena.

procedure TfrmNavigator.mUpdateFilter(pParentNode:PVirtualNode; const sFilter: string);
var
  pNode: PVirtualNode;
  pNodeData: PVTNavigatorRec;
  sText: string;
  bChildrenVisible: Boolean;
  b: Boolean;

  function mbAreChildrenVisible(pParent:PVirtualNode):Boolean;
  var
    p: PVirtualNode;
  begin
    p := pParent.FirstChild;
    Result := False;
    while p <> nil do
    begin
      Result := not vt.IsFiltered[p];
      if Result then
        Exit;
      p := p.NextSibling;
    end;
  end;
begin
  if (pParentNode = nil) or (pParentNode.ChildCount = 0) then
    Exit;
  pNode := pParentNode.FirstChild;
  while pNode <> nil do
  begin
    if pNode.ChildCount <> 0 then
    begin
      mUpdateFilter(pNode, sFilter);
      bChildrenVisible := mbAreChildrenVisible(pNode);
      vt.IsFiltered[pNode] := not bChildrenVisible;
    end
    else
    begin
      if sFilter <> '' then
      begin
        pNodeData := vt.GetNodeData(pNode);
        sText:= pNodeData^.sCaption;
        b := AnsiPos(sFilter, AnsiUppercase(sText)) = 0;
        vt.IsFiltered[pNode] :=  b;
        if not b then
        begin
          vt.VisiblePath[pNode] := True;
        end;
      end
      else
        vt.IsFiltered[pNode] := False;
    end;
    pNode := pNode.NextSibling;
  end;
end;

Podle mne to opět dokazuje jak je VT perfektní navržený nástroj.

Tagy: ,

Praxe

Komentáře

25.10.2012 2:10:33 #

TLama

Jenom dodám, že existuje hodnota enumerace toShowFilteredNodes, která když se přidá do setu TreeOptions.PaintOptions, zobrazí se i větve, které jsou vyfiltrované; pokud se z něj tato hodnota odebere, zase se schovají. To se dá v praxi použít např. jako "cache" pro funkci typu "zobrazit vše / zobrazit filtrované".

Jinak v případě, kdy se filtruje pouze několik položek stromu (což je případ výše uvedený) kdy to význam nemá, v řádu stovek je to ještě v pohodě, ale u stovek tisíců položek bych už určitě přemýšlel o incremental filtru; tedy, pokud se na konci filtračního textu objeví nový znak (nebo znaky), projdou se už jenom větve, které nejsou aktuálně vyfiltrované a ne celý strom, jako se děje v uvedeném příkladu.

TLama

25.10.2012 9:55:44 #

Radekc

toShowFilteredNodes jsem zapomněl uvést - dobré připomínky, díky.

Radekc

31.10.2012 12:51:35 #

Marek Rakowski

super příklad

díky

Marek Rakowski

10.6.2013 14:18:11 #

JBD

Neměl bys prosím ještě nějaké příklady (s vysvětlením) této komponenty? (např DB)
Prošel sem si demo, ale nejsem z toho moc chytrý...

=c((

Dík

JBD

10.6.2013 16:44:17 #

radekc

Pod článkem jsou tagy, a jeden z nich je překvapivě Virtual TreeView. To ti nestačí?

radekc

11.6.2013 0:00:56 #

JBD

Ne, nebylo to překvapení. Všechny čtyři články o Virtual TreeView, co jsou tu k nalezení, jsem si několikrát přečetl, příklady jsem zprovoznil, jen jsem úplně nepochopil to plnění dat. V příkladech používáš jako data údaje konkrétního nodu, ale pomohla by mi třeba ukázka dat z tabulky - třeba 1:N =c))
Vím, že je tu spousta lidí co by po Tobě chtěli, aby jsi za ně udělal jejich práci bez námahy. Jenže já s tím zápasím už hodně dlouho a tohle jsem zatím nebyl schopen pochopit.

Díky

JBD

21.8.2013 17:09:50 #

Martin

Zdravím VirtualTreeViewisty, každy kdo pracuje s touto komponentou jásá, ale já jsem z toho taky trochu mimo, prošel sem několik příkladů, ale stále nechápu... má někdo nebo je nědke na webu návod pro trubky? :-D
Díky

Martin

21.8.2013 18:39:52 #

radekc

Zkoušel jsi kliknout na tag virtual tree view?

radekc

Komentování ukončeno

Naše nabídka

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy).

Delphi Certified Developer

O Delphi.cz

Delphi je jediný moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64, Mac OSX a na iPhone a Android.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Poslední komentáře

Comment RSS

Dle měsíců