Autor Beitrag
Terra
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 307

Windows 7 Ultimate
Delphi® XE3
BeitragVerfasst: Di 03.11.15 15:52 
Moin,

Habe hier eine ComboBox, welche mir alle Daten aus einer Tabelle anzeigt.
Dabei werden in der ComboBox Komponente folgende Eigenschaften benutzt:
KeyField, ListField und ListSource.

Jetzt möchte ich gerne etwas mit INSERT in die SQL eintragen. Das geht auch schon !!!
Allerdings soll das eingetragene direkt in der ComboBox zu sehen sein. Sozusagen als Focus bereits ausgewählt.
Denke mal, das dieses mit dem OnDataChange im DataSource Ereignis erreicht werden könnte. Bin mir aber da nicht sicher.

Kann mir da wer weiterhelfen? Evtl. mit bissel Source?

Vielen Dank,
Terra


Moderiert von user profile iconNarses: Topic aus VCL (Visual Component Library) verschoben am Di 03.11.2015 um 15:17
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 03.11.15 16:21 
Was benutzt du denn nun tatsächlich: TComboBox oder TDBLookUpComboBox? Es handelt sich hier um zwei grundverschiedene Komponenten.

Der erstgenannten liegt lediglich eine TStrigList zugrunde, die die Einträge repräsentiert und hat mit der Datenbank nichts weiter zu tun. Wenn du die Einträge einer Spalte (eines Feldes) einer Tabelle in einer TComboBox haben möchtest, mußt du die dort via Code eintragen.

Die zweite, die TDBLookUpComboBox dient der Anzeige von Subtabellen-Werten. Beispiel: Du hast eine Haupttabelle ADRESSEN und darin ein Feld STRASSE als INT deklariert. Die eigentlichen Straßennamen verwaltest du in der Tabelle STRASSEN, den Primary Key (PK) von STRASSEN verwendest du in deiner Haupttabelle als Foreign Key (FK), um damit die Straße zu kennzeichnen.

Wenn du dir nun ein Bearbeitungsformular zum Ändern und Neuanlegen deiner Adressen zusammenbaust, kommt die TDBLookUpComboBox zum Einsatz: Dort weist du, nachdem du im die DataSource festgelegt hast, dem Property DataField das gesuchte Feld zu, indem du es aus der DropDownListe auswählst. Dem Property ListSource weist du den Namen des Datasource für die Untertabelle zu. Im Property ListFieldIndex steht der Name des PK der Tabelle STRASSEN, der gleichzeitig der FK der Tabelle ADRESSEN ist. Im Property ListField steht der Name des Feldes, das angezeigt werden soll. (Angaben gelten für FireDac, bei anderen DB-Komponenten mögen die Properties anders lauten.)

Änderst du nun den Datensatzzeiger deiner Tabelle ADRESSEN, ändert sich automatisch auch der angezeigte Straßennamen in deiner TDBLookUpComboBox.
Terra Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 307

Windows 7 Ultimate
Delphi® XE3
BeitragVerfasst: Di 03.11.15 16:27 
Also ich nutze nur TDBLookUpComboBox. Habe beim Rest nur ComboBox geschrieben, da klar sein sollte, worauf sich diese bezieht.
Wie gesagt, die Daten, die ich der Datenbank hinzufüge, sind soweit alle richtig angelegt.
Die TDBLookUpComboBox zeigt mir auch den Datensatz danach sofort ganz unten an, wenn ich die ComboBox öffne. Allerdings Fokusiert die CB den Eintrag nicht, obwohl ich auch KeyValue den Entsprechenden Wert zuweise.
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 03.11.15 16:45 
Mir ist dein Problem noch immer nicht so recht klar geworden: Verwendest du die TDBLookUpComboBox zum Nachschlagen in einer externen Tabelle? LookUp heißt auf deutsch suchen, nachschlagen, die TDBLookUpComboBox ist ausschließlich dafür gedacht, wie ich oben im Beispiel beschrieben hatte. Wenn du lediglich die Werte eines Feldes/einer Spalte darstellen willst, gibt es dafür die TDBComboBox, die im Grunde nichts anderes ist als eine TComboBox, nur daß sie die Daten eben aus einer DB-Tabelle bezieht. Weder in einer TDBLookUpComboBox noch in einer TDBComboBox kannst du Einträge ändern oder hinzufügen.

Erklär doch mal kurz, was der Hintergrund deines Problems ist bzw. was du eigentlich erreichen möchtest.
baumina
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 305
Erhaltene Danke: 61

Win 7
Delphi 10.2 Tokyo Enterprise
BeitragVerfasst: Di 03.11.15 16:58 
Eine DBLookupComboBox zeigt dir den Inhalt eines Datenfeldes. Das Datenfeld ist über DataSource und Datafield verknüpft. Wenn du nun den Feldinhalt des Datenfeldes auf den gewünschten Wert änderst, müsste alles so laufen wie du es willst.

ausblenden Delphi-Quelltext
1:
DBLookupCombobox1.Datasource.Dataset.FieldByName(DBLookupCombobox1.Datafield).AsVariant := [neuer Wert];					
Terra Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 307

Windows 7 Ultimate
Delphi® XE3
BeitragVerfasst: Di 03.11.15 19:03 
OK, in meiner Datenbank habe ich eine Tabelle (maps) mit folgenden Spalten: id, name, mapID
Die Namen sollen alle in der Combobox erscheinen. Einfach halber nutze ich dafür die TDBLookUpComboBox welche ich mit der Komponente "Absolute Database" - und zwar mit der TABSTable befülle.

In der TDBLookupcomboBox nutze ich nur die Eigenschaften KeyField (mapID), ListField (name) und ListSource (DataSource). Das funktioniert ja auch alles. Mir werden die Namen der Maps aus der Datenbank alle in der TDBLookupcomboBox angezeigt.

Ein weiteres Fenster, was ich erstellt habe, soll nur ein weiteren Eintrag für Maps hinzufügen. Das geht ja auch.
Dazu verwende ich die Query Komponente (loc_q) von Absolute Database.

Beispiel:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure Tloc_window.saveButtonClick(Sender: TObject);
var sql: string;
begin
 sql := 'INSERT INTO maps (name, mapID) VALUES (:map_name, :map_id)';
 loc_q.Close;
 loc_q.SQL.Text := sql;
 loc_q.ParamByName('map_name').Value := map_name.Text;
 loc_q.ParamByName('map_id').Value := strtoint(map_id.Text);
 loc_q.ExecSQL;

 frmMain.ComboMap.KeyValue := map_id.Text; // <-- Wird nicht gemacht - keine Ahnung warum.

 loc_window.Close;
end;


Wenn ich nach dem speichern in die ComboBox schaue, erscheint auch dort der neue Eintrag ganz unten. Dieser soll aber in dem ComboBox Feld direkt ausgewählt erscheinen. Macht es aber nicht. Das ist im Grunde mein eigentliches Problem.
In der Datenbank ist auch alles richtig eingetragen. mapID ist auch einzigartig, so das es keine doppelten Einträge geben kann.
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1180
Erhaltene Danke: 96

Win7
DXE2 Prof, Lazarus
BeitragVerfasst: Di 03.11.15 19:58 
Die Combobox dient ja dazu einen bestimmten Wert auszuwählen. Und nichts anderes musst Du machen wenn Du da einen Wert vorgeben willst.
Dein "saveButtonClick" sieht auch soweit gut aus. Es fehlt nur eine einzige Zeile, und zwar muss für die Tabelle die Du für das Lookup verwendest ein Refresh ausgeführt werden bevor Du den neuen Wert zuweist.

_________________
Solange keine Zeile Code geschrieben ist, läuft ein Programm immer fehlerfrei.
Ich teste nicht, weil ich Angst habe Fehler zu finden.
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 03.11.15 20:50 
user profile iconTerra hat folgendes geschrieben Zum zitierten Posting springen:
In der TDBLookupcomboBox nutze ich nur die Eigenschaften KeyField (mapID), ListField (name) und ListSource (DataSource). Das funktioniert ja auch alles. Mir werden die Namen der Maps aus der Datenbank alle in der TDBLookupcomboBox angezeigt.

Offensichtlich funktioniert das eben nicht, denn deine TDBLookupcomboBox zeigt eben nicht den aktuellen Datensatz an. Die Datensatz-Steuerung in einer TDBLookupcomboBox ist abhängig von der in DataSource eingetragenen Quelle, sprich: Vom Datensatzzeiger der dort eingetragenen Quelle; sie zeigt dann den jeweiligen Wert des in DataField eingetragene Feldes an, in der Regel einen Integerwert. Diese beiden Propoerties verwendest du aber gar nicht, also kann TDBLookupcomboBox auch nicht auf eine Datensatzzeiger-Änderung reagieren. Du hast ganz offensichtlich Sinn & Zweck einer TDBLookupcomboBox nicht verstanden und verwendest selbige mißbräuchlich bzw. im falschen Kontext. Auch auf die Gefahr hin, mich zu wiederholen:

TDBLookupcomboBoxen dienen dazu, in einem Eingabeformular Haupt- und Untertabellen miteinander zu verbinden. Dabei verweist die TDBLookupcomboBox in ihren Properties DataSource und DataField auf die Maintable, in den von dir verwendeten Properties KeyField, ListField und ListSource auf die Subtable. Du willst aber doch gar nichts nachschlagen: Du willst keinen Foreign-Key einer Haupttabelle mit dem Primary-Key einer Subtabelle verbinden, sondern möchtest einfach nur den jeweiligen Wert eines bestimmten Tabellenfeldes anzeigen lassen. Für deine Zwecke wäre daher die DBComboBox geeignet. Die TDBLookupcomboBox ist für deinen Zweck NICHT GEEIGNET (das bedeutet: sie paßt hier nicht), deshalb funktioniert das, was du da zusammengeklickt hast, auch nicht.

Und wenn du's nicht glaubst, propier's einfach mal aus. Mit einer TDBComboBox mußt du dich nicht um den Datensatzzeiger kümmern. Sobald du den Datensatzzeiger änderst, erfährt das die DBComboBox, sofern alles über dieselbe Query-/Table-Komponente läuft.
Terra Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 307

Windows 7 Ultimate
Delphi® XE3
BeitragVerfasst: Di 03.11.15 23:01 
Zitat:
Du willst keinen Foreign-Key einer Haupttabelle mit dem Primary-Key einer Subtabelle verbinden

Naja, das will ich schon. Regel das aber bereits über die Tabellen-Komponente von Absolute Database.


OK, und wie lass ich mir alle Datensätze aus der Tabelle in der TDBComboBox anzeigen? Verbinde ich die ComboBox mit dem DataSource, wird mir nur ein einziger Datensatz angezeigt. In meiner vorherigen Variante wurden zumindest alle Datensätze angezeigt.

Zitat:
Offensichtlich funktioniert das eben nicht, denn deine TDBLookupcomboBox zeigt eben nicht den aktuellen Datensatz an.


Mir ist auch aufgefallen, das der neue Datensatz in der TDBLookupComboBox nicht nur im Auswahlbereich angezeigt - sondern auch durch .KeyValue := map_id.Text; bzw. .KeyValue := 8; markiert wurde. Nur in dem ComboBox-Feld ist der Name nicht sichtbar.

demo

Starte ich das Programm neu, so wird mir der neu eingefügte Datensatz mit der entsprechenden mapID angezeigt. Sprich, wenn der Datensatz bereits vorhanden ist und ich erst dann das Programm öffne, wird mir alles richtig angezeigt. Nur nicht, wenn ich durch das Programm einen neuen Datensatz hinzufüge. Dann wird er nicht fokusiert.

demo2

Sind einmal alle Datensätze in die TLookupComboBox geladen (durch starten des Programms), kann ich durch ändern der KeyValue an der TLookupComboBox mir entsprechende Einträge fokussieren. Aber warum erst dann und nicht auch, wenn ich ein neuen Eintrag in die DB schreibe? Das begreife ich noch nicht so richtig.

Naja, vielleicht kann mir trotzdem jemand die Frage aus der 2. Absatz beantworten.



Danke,
Terra
Einloggen, um Attachments anzusehen!
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 03.11.15 23:46 
user profile iconTerra hat folgendes geschrieben Zum zitierten Posting springen:
Zitat:
Du willst keinen Foreign-Key einer Haupttabelle mit dem Primary-Key einer Subtabelle verbinden

Naja, das will ich schon. Regel das aber bereits über die Tabellen-Komponente von Absolute Database.

Wie regelst du das dort? Etwa mit einem persistenten Nachschlagefeld?

user profile iconTerra hat folgendes geschrieben Zum zitierten Posting springen:
OK, und wie lass ich mir alle Datensätze aus der Tabelle in der TDBComboBox anzeigen? Verbinde ich die ComboBox mit dem DataSource, wird mir nur ein einziger Datensatz angezeigt. In meiner vorherigen Variante wurden zumindest alle Datensätze angezeigt.

Das ist auch nicht Sinn & Zweck der TDBComboBox, denn dort mußt du selbst Einträge anlegen, die der Anwwender dann auswählen kann:

Für TDBListBox- und TDBComboBox-Steuerelemente müssen Sie mit dem String-Listen-Editor zur Entwurfszeit die Liste mit den anzuzeigenden Einträgen zusammenstellen. Der Stringlisten-Editor wird angezeigt, wenn Sie im Objektinspektor auf die Ellipsen-Schaltfläche in der Eigenschaft Items klicken. Geben Sie dann die gewünschten Listeneinträge ein. Zur Laufzeit können Sie mithilfe der Methoden der Eigenschaft Items die String-Liste bearbeiten.

Wenn du also doch, wie du oben schreibst, zur Auswahl die Einträge einer Subtabelle anzeigen lassen willst, dann ist jetzt doch der Einsatz einer TDBLookUpCombo, wie oben von mir bereits ausführlich beschrieben, die richtige Wahl. War diese Beschreibung irgendwie un- oder mißverständlich? Zumindest deine Angaben sind mißverständlich, denn du deutest zwar irgendwie an, daß es nun doch um zwei Tabellen geht, verwendest aber stets nur die Bezeichnung "die Tabelle". Erwartest du hier Gedankenleser oder ist es nicht eher üblich, seine Gedanken niederzuschreiben, weil man als Mensch im 21. Jahrhundert weiß, daß niemand Gedanken lesen kann?

user profile iconTerra hat folgendes geschrieben Zum zitierten Posting springen:
Mir ist auch aufgefallen, das der neue Datensatz in der TDBLookupComboBox nicht nur im Auswahlbereich angezeigt - sondern auch durch .KeyValue := map_id.Text; markiert wurde. Nur in dem ComboBox-Feld ist der Name nicht sichtbar.

Deine Verwendung der TDBLookupComboBox ist falsch: In DataSource und DataField trägst du die entsprechenden Bezeichner deiner Haupttabelle ein, die anderen drei bereits genannten Properties besetzt du mit dem DataSource der Subtabelle, dem Primarykey der Subtabelle und dem Feld der Subtabelle, das angezeigt werden soll.

Habe ich das jetzt so richtig verstanden: Du hast eine Subtabelle, die sagen wir aus einem PK und einem Bezeichner besteht, und möchtest mit der TDBLookupComboBox erreichen, daß der Anwender dort aus der Subtabelle einen der Bezeichner auswählen kann, um dessen PK in der Haupttabelle als FK einzutragen? Zusätzlich möchtest du dem Anwender gerne die Möglichkeit zur Verfügung stellen, im Falle eines Fehlens des aktuell benötigten Bezeichners der Subtabelle diesen Record selbst anzulegen. Im letzten Fall machst du einfach einen Button und gibst dem Anwender in dessen Ereignisbehandlung die Möglichkeit, z.B. in einer InputBox den entsprechenden Bezeichner anzugeben. Dort prüfst du, ob er nicht bereits existiert und ob die Eingabe auch sonst korrekt ist und legst den Bezeichner in der Subtabelle an. Dadurch wird automatisch in der TDBLookupComboBox der neue Bezeichner angezeigt, und falls nicht, lokalisierst du in eben vorher.

Und bitte: Verwende doch, auch wenn's dir schwerfällt, die korrekten Bezeichner für Komponenten. Es erschwert das Verständnis ungemein, wenn du einmal TDBLookupComboBox und dann wieder ComboBox schreibst, denn das sind in der Tat verschiedene Komponenten. Letzten Endes bist du doch derjenige, der Hilfe möchte, da ist es doch nicht zuviel verlangt, wenn du den potentiell Hilfsbereiten ein wenig entgegenkommst und deine Texte so abfaßt, daß keine unnötigen Mißverständnisse entstehen. Nicht jeder hat Lust, in solchen Fällen extra nachzufragen und sich nur deshalb, weil du dir Tipparbeit ersparen wolltest, mehr Tipparbeit aufzuhalsen.