2016-04-16 8 views
0

Ich möchte Daten aus verschiedenen SQL-Tabellen dynamisch laden und in einem TVirtualStringTree anzeigen. Dies bedeutet, dass der Header und der Inhalt jeder Spalte jedes Mal unterschiedliche Arten von Daten enthalten.So definieren Sie einen TVirtualStringTree mit dynamischer Datenstruktur

Mein Problem ist, wie in Bezug auf Speichernutzung, die Definition des Datensatzes und den Zeiger für diesen Fall zu optimieren.

Mein Denken war es wie dies zu tun:

type 
    TDataType = (dtUnknown, dtString, dtInteger, dtText, dtFloat, dtDateTime, dtDate, dtTime, dtBoolean); 

    TData = record 
    DataType: TDataType; 
    AsString: String; 
    AsInteger: Integer; 
    AsText: TStrings; 
    AsWord: Word; 
    AsDateTime: TDateTime; 
    AsDate: TDate; 
    AsTime: TTime; 
    AsBoolean: Boolean; 
    end; 
    TTreeData = array of TData; 

    PTreeData= ^TTreeData; 

In der Praxis nur 2 Felder aus dem Datensatz werden Daten enthalten: DataType (die ganze Zeit) und ein zweites Feld, hängt von den DataType definiert (zB AsString, AsInteger). Werden auch die anderen Felder als Speicher belegt, wenn Node initialisiert wird? Auch mag ich nicht, dass die DataType jedem Knoten zugeordnet ist. Es muss einen einfachen Weg geben, diesen Datensatz zu optimieren.

Bitte einige Vorschläge.

+0

Ich bin mir ziemlich sicher, dass es bereits einen datenbewussten Nachkommen dieser Komponente gibt. Hast du schon danach gesucht? Es könnte sich als effektiver erweisen als der Versuch, dieses Feature selbst neu zu erfinden. –

+0

Hier ist eine datensensitive Version von VTV: https://github.com/TurboPack/VirtualTreeView – Johan

+0

Ist es datensensitiv? Ich kann hier nur den üblichen TVirtualStringTree/TVirtualDrawTree sehen, keine neuen Komponenten und keine neuen Eigenschaften. – Andrew

Antwort

0

Wenn ich so etwas tun muss, verwende ich eine case-Anweisung im TData-Datensatz.

So etwas wie

type 
    TData = record 
     case DataType: TDataType of 
     dtUnknown: 
     (AsUnknown: ???); 
     dtString: 
     (AsString: string); // this is incorrect, string (and some others are not allowed) 
     dtInteger: 
     (AsInteger: Integer); 

     ... and so on 

     end; 
     end; 

http://docwiki.embarcadero.com/RADStudio/Seattle/en/Structured_Types#Variant_Parts_in_Records

Werfen Sie einen Blick auf TVarRec. Delphi verwendet offene Arrays TVarRec bei der Implementierung von 'array of const' Variablen und in der Format-Anweisung.

Sie benötigen wahrscheinlich nur zwei Spalten im VirtualStringTree. Eine für den Typ und andere für den Wert (dargestellt als String)

+0

@Arioch Ihre Bearbeitung, Hinzufügen von 'DataType: TDataType' als separates Feld, bevor der Variantenteil falsch ist. Es wird nicht benötigt und kann nicht mit * tag: ordinalType' * Teil identisch sein. Ich werde es entfernen. –

+0

@Greme Zu den Datentypen in varianten Teilen von Datensätzen: * Die Typen dürfen keine langen Strings, dynamische Arrays, Varianten (dh Variant-Typen) oder Schnittstellen sein, noch können sie strukturierte Typen sein, die lange Strings, dynamische Arrays enthalten , Varianten oder Schnittstellen; aber sie können Zeiger auf diese Typen sein. die Dokumente. IOW, 'AsString: String' ist nicht gültig. –

+0

@TomBrunberg Wenn Sie die Variable 'Datatype' entfernen, dann haben Sie sie nicht und verwenden sie besser nicht im' case', um den Code sauber zu halten 'case TDataType of ...'. Wichtiger ist jedoch, dass die Struktur des Topicstarters "getaggter Datensatz" ist - ähnlich wie bei DFM oder EMBL-Records beginnt er mit der Typmarkierung, und der Tail ist typabhängig. Ihre Struktur ist "zufälliger Datensatz", sie hat keinen Typmarker. Wenn der Topicstarter seinen Datenstrom analysieren würde, würde er das Tag "TDataType" lesen und dann für den Rest des Datensatzes verzweigen.Wenn Sie analysieren würden, müssten Sie stattdessen 'random (High (TDatatype)' ') aufrufen, um den Stream zu analysieren. –