![]() |
Virtual String Tree Objekte dynamisch nachladen
Hallo DpLer
Habe ein kniffliges Problem für euch. In meiner Dokumentenmanegement Software (zu 100% in Delphi geschrieben [Delphi rules :bounce1: ]) verwende ich häufig die Virtual string Tree Komponente vom Mike Lischke. In einer der Ansichten wird eine komplette Übersicht über den Dokumenteingang dargestellt. Das heist es werden alle Dokumente nach alter die jemals mit dieses System erstellt wurden in diesem Virtual String Tree dargestellt. Dabei wird einfach von einem Sql Server eine View in ein Dataset geladen und vom ersten bis zum letzten durchgelaufen. Da das System für 500.000 Dokumente ausgelegt ist muss ich die Datensicht entsprechend eingrenzen sonst dauert das laden dieser Liste ewig :kotz: Zur Zeit löse ich das einfach mit einem einstellbaren Top Statement. Ich hätte aber gern das am Anfang ca 1000 Doks geladen werden und wenn der Benutzer nach unten scrollt und bei dieser liste ganz unten angekommen ist weitere 1000 automatisch nachgeladen werden. das heist ich müsste irgendwie erkennen wenn die listview ganz unten ist und der benutzer wieder nach unten scrollen will. Gibt es da irgend eine Möglichkeit :?: :?: :?: Bin für jeden Vorschlag dankbar :dp: |
Re: Virtual String Tree Objekte dynamisch nachladen
Ich habe das mal gemacht, aber ohne eine Virtual String TreeView. Sonder mit der Normalen.
Ich hatte aber nur ca. 20 Einträge unter der Wurzel. (Level 1) Jeder Knoten hat ein Dummy-Kind (Ein Child-Knoten mit Node.Tag = 1) Im OnExpand-Ereignis der TreeView habe ich geschaut, ob die Tag-Eigenschaft des ersten Kind des zu expandierenden Knotens den Wert 1 hat. Wenn ja, wurde der Knoten wohl noch nicht expandiert. Also lade ich die Kinder dieses Knotens. Jedes Kind des Knotens bekommt ein Dummy-Kind (ein Child-Knoten mit Node.Tag = 1). Usw. Ich hatte 3 Millionen Datensätze, die so darzustellen waren. Natürlich war das blöd, wenn der anwender alle Knoten geöffnet hat, aber wer macht das schon. Schliesslich hätte er dann alle 300.000 Väter anfassen müssen. Aber, ich such mir die VirtualStringTree Komponente mal raus, weil ich in meinem aktuellen Projekt 500.000 Knoten in Level 1 habe. Und das nervt. |
Re: Virtual String Tree Objekte dynamisch nachladen
Hallo,
Zitat:
Wenn man TTreeNode.HasChildren auf True setzt wird das "+"-Zeichen dargestellt, auch wenn noch kein untergeordnetes Objekte vorhanden ist. |
Re: Virtual String Tree Objekte dynamisch nachladen
@alzaimar
vielen dank für deinen Beitrag. das mit dem dynamischen Nachladen der Kinder eines Knotens habe ich ähnlich gelöst. ich lese aus der Db aus ob bei einem entsprechenden Knoten Kinder vorhanden sind wenn ja wird ein dummy child angelegt und im onexpand des Trees die wirklichen Kinder dieses Levels nachgeladen. Bei meinem Problem allerdings habe ich keine Kinder also auch kein onexpand ereignis weil sich die ganze Liste eigentlich wie ein stringgrid verhält und sich alles in level 0 abspielt :!: :!: :!: (hab die vst für diese Lösung anderer Komponenten vorgezogen. wäre ja mit der delphi Listview (war um 500% langsamer) oder mit stringgrid auch gegangen. |
Re: Virtual String Tree Objekte dynamisch nachladen
Äch sö: Da habe ich dann ein TStringGrid genommen und einfach dynamisch nachgeladen. Wenn Du mit der MSDE arbeitest, dann setzt Du den Clustered Index auf das Feld, das bei Dir die Ordnung beschreibt. Dann schreibst Du Dir eine Stored Procedure:
SQL-Code:
Da die MyTable nach ID sortiert ist (durch den clustered index), spart sich die MSDE den Sortiervorgang und Du kannst ohne jegliche Verzögerungen ziemlich resourcenschonend (auf Serverseite!) durch die Tabelle scrollen.
Create Procedure GetTablePacket @StartID int, @Count int as
select top @Count * From MyTable Where ID >=@StartID [edit] Bei anderen DB musst du einfach schauen, über welchen Index bzw. Feld (AutoInc? Primary Key?) Du am einfachsten sortiert auf die Tabelle zugreifen kannst. [/edit] Falls Du ein Budget hast, schau Dir mal die QuantumGrid Suite von Developer Express an. Deren Grid kann mit TDatasets und auch ohne. Wenn man das datensensitiv anpackt kann man dem Teil sagen, das es bitte dynamisch laden soll. Dann kann man zwar einige Gimmicks nicht machen, wie nach Spalten sortieren und live filtern (wie z.B. Access oder Excel), aber ansonsten ist es ziemlich geil. Nebenbei kann man noch direkt Master-Detail Beziehungen einbauen. Dann hat jedes Record einen kleinen Expand-Button. Wenn man den anklickt, öffnet sich unter dem Record die Detail-Tabellen. Das Ding kostet ca. 300 Öcken. ( ![]() @Lannes: Danke für den Tip mit dem HasChildren := True. |
Re: Virtual String Tree Objekte dynamisch nachladen
hy das mit dem index ist schon klar. Hab eine DokumentID mit der ich leicht die richtigen records bekomme. obwohl ich die stringgrid komponente eigentlich nicht verwenden möchte interessiert es mich doch wie du das mit dem dynamisch nachladen gemacht hast. könntest du das bitte ein wenig genauer beschreiben.
wie gesagt möchte es mit der vst kompo lösen also wenn liste ganz unten ist (auch wenn keine zeile im string tree markiert ist) und der benutzer weiter nach unten scrollt sollen weitere x records nachgeladen werden. :-D |
Re: Virtual String Tree Objekte dynamisch nachladen
wenn du die gesamt anzahl hast füge einfach soviele nodes ein.
im on init oder beim ersten "gettext" für den node lädst du diesen dann. |
Re: Virtual String Tree Objekte dynamisch nachladen
@generic
Danke für diesen Tipp der hört sich genial an :bounce1: :coder2: :bounce1: werde das diese woche mal in angriff nehmen und ausprobieren :spin2: |
Re: Virtual String Tree Objekte dynamisch nachladen
@ generic
habe mal kurz drüber nachgedacht :coder: wenn ich angenommen im meinem recordset 15.000 dokumente vom sql server erhalte ist es ja kein problem mit recordcount diese 15000 nodes einzufügen aber :?: wenn der benutzer nach unten scrollt woher sollen die neuen nodes wissen welches dokument sie laden müssen (muss ja eine reihenfolge haben) :?: aktiviert der benutzer eine spaltensortierung würden dann ja warscheinlich die leeren nodes sortiert werden oder aber es werden dann alle geladen (das wäre kein problem) |
Re: Virtual String Tree Objekte dynamisch nachladen
Liste der Anhänge anzeigen (Anzahl: 1)
im falle einer sortierung würde alle nodes geladen bzw. das node init aufgerufen.
wenn du eine sortierung vorgibts kannst du diese mit dem sql sortieren. die datenmenge müsste dann "open" bleiben. in jedem "oninitnode" würde dann aus der datenmenge ein weiter datensatz (row) geladen. btw. ich bezweifel das ein user jemals mehr als 100 einträge sehen will. mehr sind nicht nutzbar. du solltest dann mehr mit filtern arbeiten. btw. ich hab mit delphi und mssql ein dms geschrieben. derzeit sind dort ca. 600000 dokumente drin. ich hab dir mal einen screen dran gehängt. alle listen/bäume = vst [edit] ach ja, die grundinfos sind in der regeln nicht gross. datum, name, beschreibung usw. ich denke bis ca. 10000 stück kann man die auch immer mit reinladen. die bilder oder was auch immer dann on demand |
Re: Virtual String Tree Objekte dynamisch nachladen
Was die Frage nach den 'woher sollen die nodes wissen, welche ID sie nachladen sollen' anbelangt, hatte ich Dir einen Tip gegeben.
Wenn Du einen Block lädst, weisst Du ja die ID des UNTERSTEN Records (ID_low). Beim Laden des nächten Blocks lädst Du einfach die nachsten X Records, deren ID > ID_low. Danach setzt Du ID_low wieder auf die unterste Record.ID usw. Damit kann man natürlich nicht sofort das 650.000 Dokument aus der Mitte laden. Aber das braucht man auch nicht. Natürlich kann man dann keine Sortierung mehr machen. Stell Dir vor, deine Anwendung ist im Netz und 100 Leute schauen sich das an und auf einmal drücken alle auf die Spaltenüberschrift zum Sortieren: Alle Clients saugen nun alle 100000 Dokumente... gulp. Nicht umsonst sind beim QuantumGrid diese Features im 'Gridmode' (also wenn dynamisch nachgeladen wird) ausgeschaltet. |
Re: Virtual String Tree Objekte dynamisch nachladen
@alzaimar
sorry da hätte ich auch selbst drauf kommen können :? :( danke für eure tips mir ist auch noch eine idee gekommen. ich könnte beim letzten node ganz unten einen dummy node mit einem child einfügen mit der Bezeichnung "weitere Dokumente ..." wenn dieser Knoten erweitert wird im onexpand diesen Knoten löschen den nächsten Block laden und wieder diesen dummy node einfügen. Bei jedem sortiervorgang wird der dummynode ebenfalls gelöscht und neu ganz unten erstellt. (so habe ich die Anzahl der Doks immer noch unter kontrolle die geladen werden damit mir niemand dieses system abschiesst) @generic Hört sich interessant an dein projekt Hast du eine ocr funktionalität integriert wenn ja würden mich nähere infos dazu interessieren. Hab zur Zeit aus Kostengründen noch kein ocr für direkte suche im dokument eingebaut (bewegen sich alle so ab 4000€) :coder: |
Re: Virtual String Tree Objekte dynamisch nachladen
Versuch doch mal die profane, billige, Kassenpatientenlistbox. Die hat eine Property 'Style'. Da gibst Du 'lbVirtual' ein. Alles, was Du jetzt noch brauchst, ist die 'Count' Property auf deine 650000000 zu setzen. Dann schreibst Du das OnData Event: Das gibt Dir einen Index und erwartet im Gegenzug einen String... HA!
Delphi-Quellcode:
Die Funktion Loaded (aIndex : Integer) : Boolean prüft, ob der Datensatz #aIndex schon geladen wurde. Bei der Idee mit den Blöcken kann man sich ja merken, wieviele Blöcke schon geladen wurden. Dann reduztiert sich die Funktion auf:
procedure TForm1.ListBox1Data(Control: TWinControl; Index: Integer; var Data: String);
begin If Not Loaded (Index) Then LoadBlockContaining (Index); Data := CachedData (Index); end;
Delphi-Quellcode:
Die Prozedur zum Laden eines Datenblocks sähe ungefähr so aus:
Function Loaded (aIndex : Integer) : Boolean;
Begin Result := (aIndex <= NoOfRecsLoaded); End;
Delphi-Quellcode:
GetBlock liest also einen Block von 1000 Records, deren ID > fLastID ist, und hängt ihn an deinen Cache an.
Procedure LoadBlockContaining (aIndex : Integer);
Var RecsLoaded : Integer; Begin While NoOfRecsLoaded < aIndex Do Begin GetBlock (fLastID, RecsLoaded); fLastID := RecordBlock [RecordBlock.count].ID; NoOfRecsLoaded := NoOfRecsLoaded + RecsLoaded; End; End; Damit deine SW garantiert nicht abschmiert, könntest Du noch dafür sorgen, das in deinem Cache nur die 10000 zuletzt angefassten Records sind. Da bietet sich eine LRU-Liste ("Least recently used" Verkettete Liste) an. Immer wenn auf einen Record zugegriffen wird, kommt der Record an den ANFANG der Liste. Wenn Du dann deinen Cache verkleinern musst, schmeisst Du die Records vom ENDE der Liste raus (denn die sind ja lange nicht angefasst worden). Wenn du das machst, 'verkomplizieren' sich die o.g. Routinen dezent, aber nicht wirklich tragisch. |
Re: Virtual String Tree Objekte dynamisch nachladen
Zitat:
mein dms braucht aber keine ocr im sinne von texterkennung. ich habe am meisten mit faxen zu tun welche nur 75 dpi haben und da nix leserliches mehr raus kommt. finereader engine hatte zumindest nur eine trefferrate von ca. 5%. deshalb ich nur eine erkennung von 2 dimensionalen strichcodes (wie im beispiel zu sehen). ansonsten ist mein tipp finereader engine - die ist aber teuer - laesst sich aber leicht von delphi nutzen. hat imho auch die beste erkennungsrate. |
Re: Virtual String Tree Objekte dynamisch nachladen
Nachtrag: eine ListView kennt auch einen 'Virtual Mode'. Nur heisst der OwnerData := True.
Dann noch die Items.Count Property auf die Anzahl der Dokumente setzen und das OnOwnerData überschreiben. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:46 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz