Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Problem mit Combobox.Items.AddObject() (https://www.delphipraxis.net/114494-problem-mit-combobox-items-addobject.html)

Borschti 26. Mai 2008 13:57

Datenbank: ADS • Version: 8.1 • Zugriff über: LoginDialog

Problem mit Combobox.Items.AddObject()
 
Hi,

Ich versuche einer ComboBox als Spalteninhalt den Feldinhalt einer Tabelle zu übergeben, dazu kommt noch das Ich der ComboBox mit AddObject() den Feldinhalt einer zweiten Spalte übergeben möchte.
Das klappt so weit auch ganz gut, nur habe Ich leider das Problem, dass wenn Ich auf das Object zugreife mir MANCHMAL eine EAccessViolation angezeigt wird, das passiert aber nicht bei jedem Eintrag in der ComboBox.
Ich habe schon alles mögliche ausprobiert, Ich weiß nicht ob das an dem Tabellenfeld liegt oder an meinem Code :(

Hier ist mein Code, Ich weiß einfach nicht mehr weiter. Hilfe, bitte :(

Die ComboBox_fuellen procedure wird in der zweiten Unit erzeugt.
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, VisiComboBox, Unit3, l_TreiberInit, DB, vddDataSet,
  vddReferenceDataSet, vddCustomQuery, vddQuery, vddDataSource;

type
  TForm1 = class(TForm)
    VisiComboBox1: TVisiComboBox;
    VddQuery1: TVddQuery;
    procedure FormCreate(Sender: TObject);
    procedure VisiComboBox1Select(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var Spalten : TStringList;
begin

  Treibermodule.LoginDialog.Execute;

  Spalten := TStringList.Create;

  Spalten.Add('AdrNr');
  Spalten.Add('AngelegtAm');

  ComboBox_fuellen(VisiComboBox1, VddQuery1, Spalten, 'adress');
end;

procedure TForm1.VisiComboBox1Select(Sender: TObject);
begin

  showmessage(String(VisiCombobox1.Items.Objects[VisiCombobox1.ItemIndex]));

end;

end.
Hier die zweite Unit:
Delphi-Quellcode:
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, vddDataSource, vddDataSet, vddReferenceDataSet,
  vddIndexedDataSet, vddCustomTable, vddTable, Grids, DBGrids, VisiDbGrid,
  StdCtrls, ExtCtrls, ComCtrls, VisiStatusBar, vddCustomQuery, vddQuery, Math,
  Menus, VisiListBox, VisiDbListBox, VisiComponent, VisiDbLookupControl,
  VisiDbLookupListBox, DBCtrls, VisiComboBox;

  procedure ComboBox_fuellen(ComboBox : TVisiComboBox; VddQuery : TVddQuery;
                             Spalten : TStringlist; Tabelle : String);

  type
    TPoolData = class(TObject)
  private
  public
    ID: String;
    Bezeichnung: string;
  end;

implementation

procedure ComboBox_fuellen(ComboBox : TVisiComboBox; VddQuery : TVddQuery;
                           Spalten : TStringlist; Tabelle : String);
var i : Integer;
    PoolData : TPoolData;
begin

  PoolData := TPoolData.Create;

  VddQuery.SQL.Clear;
  VddQuery.SQL.Add('Select ');

  for i := 0 to Spalten.Count -1 do
    begin
     VddQuery.SQL.Add(Spalten.Strings[i]+ ', ');
    end;

  VddQuery.SQL.Add('From ' + Tabelle);
  VddQuery.SQL.Add('Order By ' +Spalten[0]);
  VddQuery.Open;
  VddQuery.First;

  for i := 0 to VddQuery.RecordCount - 1 do
    begin
      Combobox.Items.AddObject(VddQuery.FieldByName(Spalten[0]).asString, TObject(VddQuery.Fieldbyname(Spalten[1]).asString));
      VddQuery.Next;
    end;

  Pooldata.Free;
  Spalten.Free;

end;

end.
Ich hoffe Ihr könnt mir helfen, schonmal danke für alle Antworten.

mfg
Bossi

Bernhard Geyer 26. Mai 2008 14:17

Re: Problem mit Combobox.Items.AddObject()
 
Delphi-Quellcode:
TObject(VddQuery.Fieldbyname(Spalten[1]).asString)
Und vertraust darauf das die automatische Referenzzählung von Delphi bei Strigs dir bei diesen harten Cast nicht einen Streich spielt?

Borschti 26. Mai 2008 14:25

Re: Problem mit Combobox.Items.AddObject()
 
Hmm ok, aber wie könnte Ich das anders machen? TObject() einfach weg lassen ergibt keinen Sinn da es dann garnicht mehr funktioniert. Ich müsste also eine komplett andere möglichkeit nutzen oder? Welche könnte das sein?

mfg
Bossi

Bernhard Geyer 26. Mai 2008 14:27

Re: Problem mit Combobox.Items.AddObject()
 
Eigene einfache Klasse definieren welche den String beinhaltet und entsprechend selbst erzeugen bzw. Löschen.

spaxxn 26. Mai 2008 14:36

Re: Problem mit Combobox.Items.AddObject()
 
Ne reine Stilfrage:

Zitat:

Zitat von Borschti
Delphi-Quellcode:
  VddQuery.First;
  for i := 0 to VddQuery.RecordCount - 1 do
    begin
      Combobox.Items.AddObject(VddQuery.FieldByName(Spalten[0]).asString, TObject(VddQuery.Fieldbyname(Spalten[1]).asString));
      VddQuery.Next;
    end;

Das ist ein bisschen eigenwillig :P

Sollte normalerweise so aussehen:
Zitat:

Zitat von Borschti
Delphi-Quellcode:
    VddQuery.First;
    while not VddQuery.eof do
    begin
      Combobox.Items.AddObject(VddQuery.FieldByName(Spalten[0]).asString, TObject(VddQuery.Fieldbyname(Spalten[1]).asString));
      VddQuery.Next;
    end;


Brainshock 26. Mai 2008 15:18

Re: Problem mit Combobox.Items.AddObject()
 
Anstatt den String auf TObject zu casten, solltest du lieber, wie Bernhard gesagt hat, eine Klasse für den String anlegen.

Beispiel siehe hier:

delphi.about.com - TString object

und zur Anwendung nochwas hier:

delphi.about.com - Store a String ...

Gruß,

Borschti 26. Mai 2008 16:21

Re: Problem mit Combobox.Items.AddObject()
 
Danke für die Antworten, werde mir das alles mal zu gemüte führen und die Stringklasse ausprobieren.

mfg
Bossi

Borschti 27. Mai 2008 09:15

Re: Problem mit Combobox.Items.AddObject()
 
Hallo nochmal,

also Ich komme wirklich nicht weiter. Ich habe die klasse aus dem Link von Brainshock ausprobiert und es kamen einige Fehler vor die Ich nicht nachvollziehen konnte.

Ich habe mir nochmal ein Programmierbeispiel angeschaut und bin jetzt soweit:

Die Ausgabe per ShowMessage erfolgt beim Select event der ComboBox.
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, VisiComboBox, Unit3, l_TreiberInit, DB, vddDataSet,
  vddReferenceDataSet, vddCustomQuery, vddQuery, vddDataSource;

type
  TForm1 = class(TForm)
    VisiComboBox1: TVisiComboBox;
    VddQuery1: TVddQuery;
    procedure FormCreate(Sender: TObject);
    procedure VisiComboBox1Select(Sender: TObject);
  private
    var Spalten : TStringList;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin

  Treibermodule.LoginDialog.Execute;

  Spalten := TStringList.Create;

  Spalten.Add('AdrNr');
  Spalten.Add('AngelegtAm');

  ComboBox_fuellen(VisiComboBox1, VddQuery1, Spalten, 'adress');
 
end;

procedure TForm1.VisiComboBox1Select(Sender: TObject);
begin

 PoolData := TPoolData(VisiCombobox1.Items.Objects[VisiCombobox1.ItemIndex]);
 showmessage(PoolData.var1);
end;

end.
Hier die zweite Unit mit der procedure und einer Klasse ähnlich wie Sie in dem Link beschrieben ist:
Delphi-Quellcode:
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, vddDataSource, vddDataSet, vddReferenceDataSet,
  vddIndexedDataSet, vddCustomTable, vddTable, Grids, DBGrids, VisiDbGrid,
  StdCtrls, ExtCtrls, ComCtrls, VisiStatusBar, vddCustomQuery, vddQuery, Math,
  Menus, VisiListBox, VisiDbListBox, VisiComponent, VisiDbLookupControl,
  VisiDbLookupListBox, DBCtrls, VisiComboBox;

  procedure ComboBox_fuellen(ComboBox : TVisiComboBox; VddQuery : TVddQuery;
                             Spalten : TStringlist; Tabelle : String);

  type
    TPoolData = class(TObject)
    var1: String;
    var2: string;
  end;

  var PoolData : TPoolData;
 
implementation

procedure ComboBox_fuellen(ComboBox : TVisiComboBox; VddQuery : TVddQuery;
                           Spalten : TStringlist; Tabelle : String);
var i : Integer;
begin

  PoolData := TPoolData.Create;

  VddQuery.SQL.Clear;
  VddQuery.SQL.Add('Select ');

  for i := 0 to Spalten.Count -1 do
    begin
     VddQuery.SQL.Add(Spalten.Strings[i]+ ', ');
    end;

  VddQuery.SQL.Add('From ' + Tabelle);
  VddQuery.SQL.Add('Order By ' +Spalten[0]);
  VddQuery.Open;
  VddQuery.First;

  While not VddQuery.EoF do
    begin
      PoolData.var1 := VddQuery.FieldByName(Spalten[1]).asString;
      PoolData.var2 := VddQuery.Fieldbyname(Spalten[0]).asString;
      Combobox.Items.AddObject(VddQuery.FieldByName(Spalten[0]).asString, PoolData);
      VddQuery.Next;
    end;

end;

end.
Das Problem ist jetzt, dass wenn Ich ein Item in der ComboBox auswähle mir immer nur der Feldeintrage der letzten Zeile in der Tabelle angezeigt wird, was ja auch eigentlich wegen der Schleife in der procedure klar ist.
Delphi-Quellcode:
While not VddQuery.EoF do
    begin
      PoolData.var1 := VddQuery.FieldByName(Spalten[1]).asString;
      PoolData.var2 := VddQuery.Fieldbyname(Spalten[0]).asString;
      Combobox.Items.AddObject(VddQuery.FieldByName(Spalten[0]).asString, PoolData);
      VddQuery.Next;
    end;
Aber in dem Programmierbeispiel wurde es genauso gemacht(glaube Ich zumindest oO ). Zumindest bekomme Ich schon nicht mehr die AccessViolation :)

Hier das Programmierbeispiel von dem ich die ganze Zeit rede:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, VisiComboBox, DB, vddDataSet, vddReferenceDataSet,
  vddCustomQuery, vddQuery, vddDataSource;

type
  TPoolData = class(TObject)
    ID: integer;
    Bezeichnung: string;
  end;

type
  TForm1 = class(TForm)
    VddDataSource1: TVddDataSource;
    VddQuery1: TVddQuery;
    VisiComboBox1: TVisiComboBox;
    ComboBox1: TComboBox;
    procedure FormCreate(Sender: TObject);
    procedure VisiComboBox1Select(Sender: TObject);
  private
    { Private-Deklarationen }
    PoolData : TPoolData;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;


implementation
uses l_TreiberInit;
{$R *.dfm}



procedure TForm1.FormCreate(Sender: TObject);
var id, Bez : String;
    i : Integer;
begin

  Treibermodule.LoginDialog.Execute;

  VddQuery1.SQL.Clear;
  VddQuery1.SQL.Add('Select * From ADRPOOL');
  VddQuery1.Open;
  VddQuery1.First;

  for I := 0 to VddQuery1.RecordCount - 1 do
    begin
      ID := VddQuery1.FieldByName('ID').asString;
      Bez := VddQuery1.FieldByName('Bezeichnung').asString;

      PoolData := TPoolData.Create;

      PoolData.ID         := VddQuery1.FieldByName('ID').asinteger;
      PoolData.Bezeichnung := VddQuery1.Fieldbyname('Bezeichnung').asstring;

      VisiCombobox1.Items.AddObject(Bez + ' ' + ID, PoolData);
      VddQuery1.Next;
    end;

end;


procedure TForm1.VisiComboBox1Select(Sender: TObject);
  begin
    PoolData := TPoolData(VisiCombobox1.Items.Objects[VisiCombobox1.ItemIndex]);
    showmessage(IntToStr(PoolData.ID));
  end;

end.
Ich hoffe es war nicht zuviel ;) aber Ich komme einfach nicht weiter :(

mfg
Bossi

spaxxn 27. Mai 2008 09:31

Re: Problem mit Combobox.Items.AddObject()
 
Derzeit instanzierst du in ComboBox_fuellen nur ein Objekt und hängst dieses an alle Einträge ran. Im FormCreate hingegen erstellst du für jeden Eintrag eine eigene Instanz. Ist das so von dir gewollt?

Ausserdem: Pass doch auch im FormCreate die Schleife für die Datensätze an :P


Delphi-Quellcode:
procedure ComboBox_fuellen(ComboBox : TVisiComboBox; VddQuery : TVddQuery;
                           Spalten : TStringlist; Tabelle : String);
var i : Integer;
begin

 

  VddQuery.SQL.Clear;
  VddQuery.SQL.Add('Select ');

  for i := 0 to Spalten.Count -1 do
    begin
     VddQuery.SQL.Add(Spalten.Strings[i]+ ', ');
    end;

  VddQuery.SQL.Add('From ' + Tabelle);
  VddQuery.SQL.Add('Order By ' +Spalten[0]);
  VddQuery.Open;
  VddQuery.First;

  While not VddQuery.EoF do
    begin
      PoolData := TPoolData.Create;
      PoolData.var1 := VddQuery.FieldByName(Spalten[1]).asString;
      PoolData.var2 := VddQuery.Fieldbyname(Spalten[0]).asString;
      Combobox.Items.AddObject(VddQuery.FieldByName(Spalten[0]).asString, PoolData);
      VddQuery.Next;
    end;

end;
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var id, Bez : String;
begin

  Treibermodule.LoginDialog.Execute;

  VddQuery1.SQL.Clear;
  VddQuery1.SQL.Add('Select * From ADRPOOL');
  VddQuery1.Open;
  VddQuery1.First;

  while not VddQuery1.eof do
    begin
      ID := VddQuery1.FieldByName('ID').asString;
      Bez := VddQuery1.FieldByName('Bezeichnung').asString;

      PoolData := TPoolData.Create;

      PoolData.ID         := VddQuery1.FieldByName('ID').asinteger;
      PoolData.Bezeichnung := VddQuery1.Fieldbyname('Bezeichnung').asstring;

      VisiCombobox1.Items.AddObject(Bez + ' ' + ID, PoolData);
      VddQuery1.Next;
    end;

end;

Borschti 27. Mai 2008 09:53

Re: Problem mit Combobox.Items.AddObject()
 
Also
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var id, Bez : String;
begin

  Treibermodule.LoginDialog.Execute;

  VddQuery1.SQL.Clear;
  VddQuery1.SQL.Add('Select * From ADRPOOL');
  VddQuery1.Open;
  VddQuery1.First;

  while not VddQuery1.eof do
    begin
      ID := VddQuery1.FieldByName('ID').asString;
      Bez := VddQuery1.FieldByName('Bezeichnung').asString;

      PoolData := TPoolData.Create;

      PoolData.ID         := VddQuery1.FieldByName('ID').asinteger;
      PoolData.Bezeichnung := VddQuery1.Fieldbyname('Bezeichnung').asstring;

      VisiCombobox1.Items.AddObject(Bez + ' ' + ID, PoolData);
      VddQuery1.Next;
    end;

end;
Ist ja nur aus dem Programmierbeispiel, das benutze Ich in meinem eigentlich Programm ja nicht.

Hier geschieht der Aufruf der procedure, das Formcreate und das ComboBoxSelect Ereignis:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, VisiComboBox, Unit3, l_TreiberInit, DB, vddDataSet,
  vddReferenceDataSet, vddCustomQuery, vddQuery, vddDataSource;

type
  TForm1 = class(TForm)
    VisiComboBox1: TVisiComboBox;
    VddQuery1: TVddQuery;
    procedure FormCreate(Sender: TObject);
    procedure VisiComboBox1Select(Sender: TObject);
  private
    var Spalten : TStringList;
    { Private-Deklarationen } 
  public
    { Public-Deklarationen } 
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm} 

procedure TForm1.FormCreate(Sender: TObject);
begin

  Treibermodule.LoginDialog.Execute;

  Spalten := TStringList.Create;

  Spalten.Add('AdrNr');
  Spalten.Add('AngelegtAm');

  ComboBox_fuellen(VisiComboBox1, VddQuery1, Spalten, 'adress');
 
end;

procedure TForm1.VisiComboBox1Select(Sender: TObject);
begin

PoolData := TPoolData(VisiCombobox1.Items.Objects[VisiCombobox1.ItemIndex]);
showmessage(PoolData.var1);
end;

end.
mfg
Bossi


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:02 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz