Delphi 7 Version Hier ist ein Beispiel, wie man das erreicht. Ich habe Delphi2010 verwendet, um es zu implementieren, aber es sollte zumindest in Delphi7 funktionieren, da ich die Typinfo-Einheit direkt verwendete.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
ListBox1: TListBox;
Edit1: TEdit;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
FList: TList;
procedure DoSort(PropName: String);
procedure DoDisplay(PropName: String);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
TypInfo;
var
PropertyName: String;
type
TPerson = class
private
FName: String;
FAge: Integer;
published
public
constructor Create(Name: String; Age: Integer);
published
property Name: String read FName;
property Age: Integer read FAge;
end;
{ TPerson }
constructor TPerson.Create(Name: String; Age: Integer);
begin
FName := Name;
FAge := Age;
end;
function ComparePersonByPropertyName(P1, P2: Pointer): Integer;
var
propValueP1, propValueP2: Variant;
begin
propValueP1 := GetPropValue(P1, PropertyName, False);
propValueP2 := GetPropValue(P2, PropertyName, False);
if VarCompareValue(propValueP1, propValueP2) = vrEqual then begin
Result := 0;
end else if VarCompareValue(propValueP1, propValueP2) = vrGreaterThan then begin
Result := 1;
end else begin
Result := -1;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FList := TList.Create;
FList.Add(TPerson.Create('Zed', 10));
FList.Add(TPerson.Create('John', 20));
FList.Add(TPerson.Create('Mike', 30));
FList.Add(TPerson.Create('Paul', 40));
FList.Add(TPerson.Create('Albert', 50));
FList.Add(TPerson.Create('Barbara', 60));
FList.Add(TPerson.Create('Christian', 70));
Edit1.Text := 'Age';
DoSort('Age'); // Sort by age
DoDisplay('Age');
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DoSort(Edit1.Text);
DoDisplay(Edit1.Text);
end;
procedure TForm1.DoSort(PropName: String);
begin
PropertyName := PropName;
FList.Sort(ComparePersonByPropertyName);
end;
procedure TForm1.DoDisplay(PropName: String);
var
i: Integer;
strPropValue: String;
begin
ListBox1.Items.Clear;
for i := 0 to FList.Count - 1 do begin
strPropValue := GetPropValue(FList[i], PropName, False);
ListBox1.Items.Add(strPropValue);
end;
end;
end.
BTW, habe ich ein einfaches Formular mit einem listbox, ein bearbeiten und Taste. Die Listbox zeigt den Inhalt der Liste (FList) sortiert an. Die Schaltfläche wird verwendet, um die Liste nach dem zu sortieren, was der Benutzer in der Bearbeitungsbox eingegeben hat.
Delphi 2010 Version (Verweise auf Methoden verwendet)
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm2 = class(TForm)
ListBox1: TListBox;
Edit1: TEdit;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
FList: TList;
FPropertyName: String; { << }
procedure DoSort(PropName: String);
procedure DoDisplay(PropName: String);
function CompareObjectByPropertyName(P1, P2: Pointer): Integer; { << }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
uses
TypInfo;
type
TPerson = class
private
FName: String;
FAge: Integer;
published
public
constructor Create(Name: String; Age: Integer);
published
property Name: String read FName;
property Age: Integer read FAge;
end;
{ TPerson }
constructor TPerson.Create(Name: String; Age: Integer);
begin
FName := Name;
FAge := Age;
end;
/// This version uses a method to do the sorting and therefore can use a field of the form,
/// no more ugly global variable.
/// See below (DoSort) if you want to get rid of the field also ;)
function TForm2.CompareObjectByPropertyName(P1, P2: Pointer): Integer; { << }
var
propValueP1, propValueP2: Variant;
begin
propValueP1 := GetPropValue(P1, FPropertyName, False);
propValueP2 := GetPropValue(P2, FPropertyName, False);
if VarCompareValue(propValueP1, propValueP2) = vrEqual then begin
Result := 0;
end else if VarCompareValue(propValueP1, propValueP2) = vrGreaterThan then begin
Result := 1;
end else begin
Result := -1;
end;
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
FList := TList.Create;
FList.Add(TPerson.Create('Zed', 10));
FList.Add(TPerson.Create('John', 20));
FList.Add(TPerson.Create('Mike', 30));
FList.Add(TPerson.Create('Paul', 40));
FList.Add(TPerson.Create('Albert', 50));
FList.Add(TPerson.Create('Barbara', 60));
FList.Add(TPerson.Create('Christian', 70));
Edit1.Text := 'Age';
DoSort('Age'); // Sort by age
DoDisplay('Age');
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
DoSort(Edit1.Text);
DoDisplay(Edit1.Text);
end;
procedure TForm2.DoSort(PropName: String);
begin
FPropertyName := PropName; { << }
FList.SortList(CompareObjectByPropertyName); { << }
/// The code above could be written with a lambda, and without CompareObjectByPropertyName
/// using FPropertyName, and by using a closure thus referring to PropName directly.
/// Below is the equivalent code that doesn't make use of FPropertyName. The code below
/// could be commented out completely and just is there to show an alternative approach.
FList.SortList(
function (P1, P2: Pointer): Integer
var
propValueP1, propValueP2: Variant;
begin
propValueP1 := GetPropValue(P1, PropName, False);
propValueP2 := GetPropValue(P2, PropName, False);
if VarCompareValue(propValueP1, propValueP2) = vrEqual then begin
Result := 0;
end else if VarCompareValue(propValueP1, propValueP2) = vrGreaterThan then begin
Result := 1;
end else begin
Result := -1; /// This is a catch anything else, even if the values cannot be compared
end;
end);
/// Inline anonymous functions (lambdas) make the code less readable but
/// have the advantage of "capturing" local variables (creating a closure)
end;
procedure TForm2.DoDisplay(PropName: String);
var
i: Integer;
strPropValue: String;
begin
ListBox1.Items.Clear;
for i := 0 to FList.Count - 1 do begin
strPropValue := GetPropValue(FList[i], PropName, False);
ListBox1.Items.Add(strPropValue);
end;
end;
end.
ich die mit { << }
die wichtigsten Änderungen.
Oh, wenn Sie Delphi2010 haben, dann können Sie ein Lambda verwenden, um die globale Variable loszuwerden, indem Sie ComparePersonByPropertyName in eine Methode verwandeln und statt Sort() müssen Sie SortList() verwenden – Trinidad
Danke Trinidad. Das ist wahrscheinlich der Ansatz, den ich am Ende verwenden werde (der Code oben). Ich denke, die einzige andere Option ist, eine abgeleitete TList zu erstellen und meine eigene schnelle Sortierung zu implementieren, die einen Eigenschaftsnamenparameter akzeptiert oder zumindest eine Methode (Prozedur des Objekts) als einen Parameter für die Sortiermethode und nicht nur eine Prozedur akzeptiert . – GrandmasterB