Avatar billede sorenriis Nybegynder
31. januar 2006 - 14:54 Der er 3 kommentarer og
1 løsning

Vise data i tabel

Jeg er lidt i tvivl om hvordan jeg gør det nedenstående bedst, så jeg håber at "ekspertene" herinde kan hjælpe :-)

Sagen er den at der til mit program bliver sendt en pakke med en klump data (fornavn, efternavn, email og telefonnummer) via TCP.
Disse data vil jeg gerne havde sat ind i en tabel i det øjeblik de modtages (en række pr. datasæt).

Når så næste datasæt modtages skal dette også indsættes i tabellen. Men problemet nu er at de skal sorteres efter f.eks.  efternavn. Hvordan kan det klares i Delphi?

Det skal desuden være sådan at hvis jeg klikker på en række, skal det være muligt at arbejde på de data i den række jeg markerede.

Hvordan laves alt dette mest effektivt i Delphi 2005?
Hovedsageligt leder jeg efter ideer til hvordan det gøres, så  jeg forventer ikke at al koden leveret på et sølvfad :)
Avatar billede Henrik_B Novice
31. januar 2006 - 16:40 #1
Hej Søren.

1. Er der een eller flere records i dit input-datasæt ?
2 Du skriver tabel, men er det en flad fil, eller en database, og i givet fald hvilken ?

Det nemmeste ville være at gemme dem i en tabel i en database, f.eks. MySQL. Al sorteringen af data kan klares af database-systemet, så du skal koncentrere dig om brugerinterfacet.
Avatar billede hrc Mester
31. januar 2006 - 22:54 #2
Den ikke SQL-baserede løsning er, at bruge en TListView komponent, hvor du laver sortering på kolonnerne.

Hver person-objekt kan så hægtes på TListItem.Data property'en så du har objektets data ved hånden hvis du eksempelvis dobbeltklikker på linien.

Ved rettelse af en linie kan du enten lave en rettedialog eller lade TEdit'er flyde ovenpå felterne i TListView'et. Det sidste er ret besværligt.

Dine person-objekter kan du enten lade hænge på dit listview og slette dem via OnDeletion-eventet og/eller have dem i en TObjectList parallelt med listview'et.

--------------------------------------------------------------
Din TPerson ville jeg lave i retning af dette (Unitten forst):
--------------------------------------------------------------

type
  TPerson = class
  private
    fFornavn : string;
    fEfternavn : string;
    ...
  public
    // Opret vha. dine dataklumper
    constructor Create(aStream : TStream); overload;
    // Opret via en dialog i programmet
    constructor Create(aFornavn, aEfternavn, aAdresse, aPostnr, aEmail, aTlf : string); overload;
    property Fornavn : string read fFornavn;
    property Efternavn : string read fEfternavn;
    ...
    function Edit(aOwner : TComponent) : boolean; // Til at rette personen
    procedure FillListItem(aListItem : TListItem); // Til at hægte sig på listviewet
  end;

  // Egentlig ikke nodvendig, men jeg plejer at tage den med.
  TPersonList = class(TObjectList)
  private
  public
    property Item[const aIndex : integer] : TPerson read GetPerson; default;
    procedure FillListView(aListView : TListView);
  end;

implementation

{ TPerson }

...

// Fyld én record i listview
procedure TPerson.FillListItem(aListItem : TListItem);
begin
  aListItem.SubItems.Clear;
  aListItem.Data := self; // Hægt objektet på listitem'et.
  aListItem.Caption := fFornavn + ' ' + fEfternavn;
  aListItem.SubItems.Add(fEMail);
  aListItem.SubItems.Add(fTlf);
end;

{ TPersonList }

...

// Listens "Fyld alle data i listviewet" ser således ud:
procedure TPersonList.FillListView(aListView : TListView);
var
  i : integer;
begin
  aListView.Items.BeginUpdate;
  try
    aListView.Items.Clear;
    for i := 0 to Count - 1 do
      Item[i].FillListItem(aListView.Items.Add);
  finally
    aListView.Items.EndUpdate;
  end;
end;

-----------------------
Skelettet til din form:
-----------------------

Når du så har et TPerson-objekt klar til visning i dit listview:

procedure TForm1.DataReadyEllerSaadanNoget(aStream : TStream);
var
  Person : TPerson;
  ListItem : TListItem;
begin
  // Person-objektet ved hvordan det skal håndtere din dataklump
  Person := TPerson.Create(aStream);
  // Opret listitem
  ListItem := ListView1.Items.Add;
  // Person-objektet ved hvordan det skal præsentere din dataklump i et listview
  Person.FillListItem(ListItem);
end;
 
Dit listview har en OnColumnClick og en OnCompare som du skal bruge til sortering (i øvrigt lavet pænere i .NET):

  TForm1 = class(TForm)
  private
    fColumnClicked : integer; // Hvilken kolonne blev klikket
    fSortAscending : boolean; // Hvilken retning skal der sorteres
  public
  end;

procedure TForm1.ListView1ColumnClick(Sender: TObject; Column: TListColumn);
begin
  if fColumnClicked = Column.Index then
    fSortAscending := not fSortAscending
  else begin
    fColumnClicked := Column.Index;
    fSortAscending := true;
  end;
  // Sæt eventuelle sorteringspile her
  (Sender as TListView).AlphaSort;
end;

procedure TForm1.ListView1Compare(Sender: TObject;
            Item1, Item2: TListItem; Data: Integer; var Compare: Integer);
var
  p1, p2 : TPerson;
begin
  p1 := Item1.Data;
  p2 := Item2.Data;
  case fColumnClicked of
    0 : begin
          Compare := CompareStr(p1.Efternavn, p2.Efternavn);
          if Compare = 0 then // Jensen = Jensen, prøv fornavn
            Compare := CompareStr(p1.Fornavn, p2.Fornavn);
        end;
    1 : Compare := CompareStr(p1.Email, p2.Email);
    2 : Compare := CompareStr(p1.Tlf, p2.Tlf);
  end;
  if not fSortAscending then // Vend sorteringsorden
    Compare := -Compare;
end;

Endelig så kan du få ListView'et til at slette objektet når du sletter en linie:

// Hvis du har en parallel liste til dine personer
procedure TForm1.ListView1Deletion(Sender: TObject; Item: TListItem);
var
  Person : TPerson;
begin
  // Den korte up‘dagogiske version er : fPersonList.Remove(Item.Data);
  Person := Item.Data;
  fPersonList.Remove(Person);
end;

// Hvis listviewet er "listen"
procedure TForm1.ListView1Deletion(Sender: TObject; Item: TListItem);
var
  Person : TPerson;
begin
  // Den korte up‘dagogiske version er : TPerson(Item.Data).Free;
  Person := Item.Data;
  Person.Free;
end;
Avatar billede sorenriis Nybegynder
01. februar 2006 - 11:07 #3
fs-manden:
ad1. Det der kommer ind via TCP er en buffer indeholdende et recordsæt bestående af 4 "variable" (fornavn, efternavn, email og telefonnummer).
ad2. Jeg bare have smidt data'ene ind i en tabel så de kan ses. Der skal ikke arbejdes med data'ene som sådan, man skal blot kunne markere, indlæse og slette fra tabellen.

Hvordan ville du evt. klare det hvis du smed data'ene i en database først (hvilken databasetype ville du anvende)?

hrc:
Tak for svaret. Det vil jeg kigge lidt på :)
Avatar billede hrc Mester
07. februar 2006 - 08:35 #4
Du skal bare sprøge om der er noget der driller. Det er en løsningsmodel jeg har brugt utallige gange og den virker for mig; især efter jeg fandt TObjectList'en.

Hvis det er lidt uoverskueligt så skyldes det at jeg pakker lidt meget sammen i en "post".

Der er:
- Brugen af data objekter (som ved hvordan de læses fra en strem og derefter præsenteres.
- Brugen af TObjectList
- Brugen af TListView (incl. sortering af kolonner)

- Endelig muligheden for at bruge "konceptet" med TObjectList eller glemme den.

Der er mange ting.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester