AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TComboBox mit Aliaswerten

Offene Frage von "MiniMatrix"
Ein Thema von MiniMatrix · begonnen am 31. Jul 2014 · letzter Beitrag vom 31. Jul 2014
Antwort Antwort
MiniMatrix

Registriert seit: 5. Feb 2010
16 Beiträge
 
#1

TComboBox mit Aliaswerten

  Alt 31. Jul 2014, 11:51
Ich hätt da maln Problem...

Wenn man mit einer ComboBox (Stringlisten) arbeitet, so hat man meiner Meinung nach den unschönen Zustand, das als Selektionsergebnis (kein Multiselekt) quasi nur die Eigenschaft "Text" oder ItemIndex zur Verfügung steht. Insbesondere ItemIndex ist sehr unschön, da es den Index des Eintrages liefert. Dies ist solange kein wirkliches Problem, solange man die Liste am Ende um neue Werte ergänzt. Aber spätestens, wenn der Anwender die Liste sortiert haben möchte, und man den Index gespeichert hat, hat man ein ernstes Problem. Speichert man hingegen den Text selbst und nicht den Index, so bekommt man schnell beim Thema "Mehrsprachigkeit" wiederum ein ernstes Problem.
Viel sinniger wäre in meinen Augen, die Werteliste mit Aliaswerten anzureichern, die nicht den Index wiederspiegeln.
Also statt:

"Banane" 0
"Apfel" 1
"Kirsche" 2
"Erdbeere" 3

besser:
"Banane" "0"
"Apfel" "1"
"Kirsche" "2"
"Erdbeere" "3"

Items:
"Banane=0"
"Apfel=1"
"Kirsche=2"
"Erdbeere=3"

Die Eigneschaft "Text" würde bei gewähltem Eintrag "Apfel" auch "Apfel" lauten, und ItemIndex 1, die (fehlende) Eigenschaft TextAlias oder ItemAlias müsste "1" liefern. Und wenn man diese Eigenschaft setzt, müsste die Komponente den entsprechenden Wert auch als ausgewählt anzeigen (Eigenschaften Text und ItemIndex müssen entsprechend gesetzt werden).

Kennt jemand eine Combobox Komponente, die genau so was kann?
Oder hat jemand eine Idee, wie man dies auf Basis der Delphi Standardkomponenten bauen könnte?
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.625 Beiträge
 
Delphi 12 Athens
 
#2

AW: TComboBox mit Aliaswerten

  Alt 31. Jul 2014, 11:55
Pack doch Deine Aliaswerte in eine Klasse, die Du dann mit AddObject den Items der ComboBox hinzufügst.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
MiniMatrix

Registriert seit: 5. Feb 2010
16 Beiträge
 
#3

AW: TComboBox mit Aliaswerten

  Alt 31. Jul 2014, 14:38
Nunja, die Idee mit AddObject hatte ich auch schon, aber da fehlt mir eine Menge an "Komfort" und es müsste noch einiges gebaut werden, andernfalls müsste dann jedesmal wieder was gebaut werden.
Eine Komponente, die einfach zu verwenden wäre, ist da schon eher mein Ding. Leider stecke ich in der VCL nicht so wirklich tief drin (Delphi 2007) und tue mir da schwer.

Trotzdem habe ich einmal einen absolut nicht funktionierenden "Rumpf" gebaut. Jeder Versuch der Klasse ein Item oder eine Liste hinzuzufügen scheitert. Das erste Problem hierbei scheint wohl, das die Items vom Type TStrings sind und nicht vom Typ TStringList (wie ich erwartet hätte. Wo sind die dann gespeichert?) - also keine Werte selbst halten.
Die zweite Schwierigkeit ist, das Objekte, die der Liste hinzugefügt werden, auch selbst wieder gelöscht werden müssen (laut Doku).

Delphi-Quellcode:
unit AliasComboBox;

interface

uses
  SysUtils, Classes, Controls, StdCtrls;

type
  TAliasComboBox = class( TCustomComboBox )
  private
    { Private-Deklarationen }
  protected
    { Protected-Deklarationen }
    function GetItemsClass: TCustomComboBoxStringsClass; override;
    procedure SetItems( const Value: TStrings ); override;
    function GetItemAlias: String;
    procedure SetItemAlias( sAlias: String );
  public
    { Public-Deklarationen }
  published
    { Published-Deklarationen }
    property Align;
    property AutoComplete default True;
    property AutoCompleteDelay default 500;
    property AutoDropDown default False;
    property AutoCloseUp default False;
    property BevelEdges;
    property BevelInner;
    property BevelKind default bkNone;
    property BevelOuter;
    property Style; {Must be published before Items}
    property Anchors;
    property BiDiMode;
    property CharCase;
    property Color;
    property Constraints;
    property Ctl3D;
    property DragCursor;
    property DragKind;
    property DragMode;
    property DropDownCount;
    property Enabled;
    property Font;
    property ImeMode;
    property ImeName;
    property ItemAlias: String read GetItemAlias write SetItemAlias;
    property ItemHeight;
    property ItemIndex default -1;
    property MaxLength;
    property ParentBiDiMode;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property Sorted;
    property TabOrder;
    property TabStop;
    property Text;
    property Visible;
    property OnChange;
    property OnClick;
    property OnCloseUp;
    property OnContextPopup;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnDrawItem;
    property OnDropDown;
    property OnEndDock;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMeasureItem;
    property OnMouseEnter;
    property OnMouseLeave;
    property OnSelect;
    property OnStartDock;
    property OnStartDrag;
    property Items; { Must be published after OnMeasureItem }
  end;//of class

procedure Register;

implementation

//==============================================================================
procedure Register;
begin
  RegisterComponents( 'Beispiele', [ TAliasComboBox ]);
end;//of procedure

//======================================================================== Types
type
  TAliasComboBoxStrings = class( TCustomComboBoxStrings )
  public
    procedure Delete(Index: Integer); override;
  end;//of class

type
  TAlias = class( TObject )
  private
    { Private-Deklarationen }
    FAlias: String;
  protected
    { Protected-Deklarationen }
  public
    { Public-Deklarationen }
    constructor CreateAlias( sAlias: String ); virtual;
  published
    { Published-Deklarationen }
    property Alias: String read FAlias;
  end;//of class


//======================================================== TAliasComboBoxStrings
procedure TAliasComboBoxStrings.Delete( Index: Integer );
var
  aObj: TObject;
begin
  if( 0 > Index )
  then //Do nothing
  else begin
       //Löschen des erzeugten Objektes
       aObj:= GetObject( Index );
       aObj.Free;
       aObj := nil;
       PutObject( Index, aObj );
       end;//of if

  inherited Delete( Index );
end;//of procedure

//======================================================================= TAlias
constructor TAlias.CreateAlias( sAlias: String );
begin
  inherited Create();

  FAlias := sAlias;
end;//of constructor

//=============================================================== TAliasComboBox
function TAliasComboBox.GetItemsClass: TCustomComboBoxStringsClass;
begin
  Result := TAliasComboBoxStrings;
end;//of function

//------------------------------------------------------------------------------
procedure TAliasComboBox.SetItems( const Value: TStrings );
var
  iCount: Integer;
begin
  inherited SetItems( Value );

  if( not Assigned( Value ))
  then //Do nothing
  else if( 0 >= Value.Count )
  then //Do nothing
  else begin
       for iCount := 0 to Value.Count - 1 do
         begin
         Items.Objects[ iCount ]:= TAlias.CreateAlias( Trim( Value.ValueFromIndex[ iCount ]));
         Items.Strings[ iCount ]:= Trim( Items.Names[ iCount ]);
         end;//of for
       end;//of else
end;//of procedure

//------------------------------------------------------------------------------
function TAliasComboBox.GetItemAlias: String;
begin
  if( 0 > ItemIndex )
  then Result := ''
  else Result := TAlias( Items.Objects[ ItemIndex ]).Alias;
end;//of function

//------------------------------------------------------------------------------
procedure TAliasComboBox.SetItemAlias( sAlias: String );
var
  bDoChg: Boolean;
  iCount: Integer;
begin
  if( 0 > ItemIndex )
  then bDoChg:= True
  else if( sAlias <> TAlias( Items.Objects[ ItemIndex ]).Alias )
  then bDoChg:= True
  else bDoChg:= False;

  if( bDoChg )
  then begin
       for iCount := 0 to Items.Count - 1 do
         begin
         if( 0 = CompareText( sAlias, TAlias( Items.Objects[ ItemIndex ]).Alias ))
         then begin
              ItemIndex := iCount;
              Text := Items[ iCount ];
              Break;//of for
              end;//of for
         end;//of for
       end;//of if
end;//of procedure

end.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: TComboBox mit Aliaswerten

  Alt 31. Jul 2014, 14:50
Du gehst das von der falschen Seite an

Erstelle dir eine ObjektListe mit allen benötigten Informationen:
  • Label-Text
  • Echter Wert
Den Label-Text packst du in die ComboBox in der gleichen Reihenfolge wie in der Liste und der ItemIndex zeigt dir das Objekt in der Liste.
Wenn jetzt sortiert werden soll, dann sortierst du die Liste und fängst von vorne an (Label-Text in ComboBox)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
MiniMatrix

Registriert seit: 5. Feb 2010
16 Beiträge
 
#5

AW: TComboBox mit Aliaswerten

  Alt 31. Jul 2014, 17:12
Der Tipp mit der Objektliste war super. Danke dafür.

Hier die Version 1.0 (Anmerkungen und Verbesserungen bitte hier posten):

Delphi-Quellcode:
unit AliasComboBox;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, Contnrs;

type
  TAliasObj = class( TObject )
  private
    { Private-Deklarationen }
    FLabel: String;
    FValue: String;
  protected
    { Protected-Deklarationen }
  public
    { Public-Deklarationen }
    constructor CreateAlias( sLabel, sValue: String ); virtual;
  published
    { Published-Deklarationen }
    property Value: String read FLabel;
    property Alias: String read FValue;
  end;//of class

type
  TAliasComboBox = class( TCustomComboBox )
  private
    { Private-Deklarationen }
    FAliasList: TObjectList;
  protected
    { Protected-Deklarationen }
    function GetAliasForLabel( sLabel : String ): String;
    function GetLabelForAlias( sAlias : String ): String;
    function GetItemAlias : String;
    procedure SetItemAlias ( sAlias : String );
    procedure AddSingleItemVal( sValue : String );
    procedure AddItem ( Item : String;
                                      aObject: TObject ); override;
    procedure SetItems ( const Value : TStrings ); override;
  public
    { Public-Deklarationen }
    constructor Create ( aOwner : TComponent ); override;
    destructor Destroy; override;
    procedure Clear; override;
    procedure AddAliasItem ( sLabel : String;
                                      sValue : String ); virtual;
    procedure AddAliasStrings( aList : TStrings ); virtual;
  published
    { Published-Deklarationen }
    property Align;
    property AutoComplete default True;
    property AutoCompleteDelay default 500;
    property AutoDropDown default False;
    property AutoCloseUp default False;
    property BevelEdges;
    property BevelInner;
    property BevelKind default bkNone;
    property BevelOuter;
    property Style; {Must be published before Items}
    property Anchors;
    property BiDiMode;
    property CharCase;
    property Color;
    property Constraints;
    property Ctl3D;
    property DragCursor;
    property DragKind;
    property DragMode;
    property DropDownCount;
    property Enabled;
    property Font;
    property ImeMode;
    property ImeName;
    property ItemAlias: String read GetItemAlias write SetItemAlias;
    property ItemHeight;
    property ItemIndex default -1;
    property MaxLength;
    property ParentBiDiMode;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property Sorted;
    property TabOrder;
    property TabStop;
    property Text;
    property Visible;
    property OnChange;
    property OnClick;
    property OnCloseUp;
    property OnContextPopup;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnDrawItem;
    property OnDropDown;
    property OnEndDock;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMeasureItem;
    property OnMouseEnter;
    property OnMouseLeave;
    property OnSelect;
    property OnStartDock;
    property OnStartDrag;
    property Items; { Must be published after OnMeasureItem }
  end;//of class

procedure Register;

implementation

//==============================================================================
procedure Register;
begin
  RegisterComponents( 'Beispiele', [ TAliasComboBox ]);
end;//of procedure

//==================================================================== TAliasObj
constructor TAliasObj.CreateAlias( sLabel, sValue: String );
begin
  inherited Create();

  FLabel:= sLabel;
  FValue:= sValue;
end;//of constructor

//=============================================================== TAliasComboBox
constructor TAliasComboBox.Create( aOwner: TComponent );
begin
  inherited Create( aOwner );

  FAliasList:= TObjectList.Create;
end;//of constuctor

//------------------------------------------------------------------------------
destructor TAliasComboBox.Destroy;
begin
  if( Assigned( FAliasList ))
  then FAliasList.Free;

  inherited Destroy;
end;//of destructor

//------------------------------------------------------------------------------
procedure TAliasComboBox.Clear;
begin
  if( Assigned( FAliasList ))
  then FAliasList.Clear;

  inherited Clear;
end;//of procedure

//------------------------------------------------------------------------------
procedure TAliasComboBox.AddAliasItem( sLabel, sValue: String );
begin
  if( Assigned( FAliasList ))
  then FAliasList.Add( TAliasObj.CreateAlias( sLabel, sValue ));
  Items.Add( sLabel );
end;//of procedure

//------------------------------------------------------------------------------
procedure TAliasComboBox.AddAliasStrings( aList: TStrings );
var
  iCount: Integer;
begin
  if( Assigned( FAliasList ))
  then FAliasList.Clear;
  Items.Clear;

  if( Assigned( aList ))
  then begin
       Items.BeginUpdate;

       for iCount := 0 to aList.Count - 1 do
         begin
         AddSingleItemVal( aList.Strings[ iCount ]);
         end;//of for

       Items.EndUpdate;
       end;//of if
end;//of procedure

//------------------------------------------------------------------------------
function TAliasComboBox.GetAliasForLabel( sLabel: String ): String;
var
  iCount: Integer;
  iPos : Integer;
begin
  Result := '';
  sLabel := Trim( sLabel );
  if( '' <> sLabel )
  then begin
       iPos := Pos( Items.NameValueSeparator,
                    sLabel );
       if( 0 < iPos )
       then sLabel := Trim( Copy( sLabel, 1, iPos - 1 ));
       Result := sLabel;
       if( Assigned( FAliasList ))
       then begin
            for iCount := 0 to FAliasList.Count - 1 do
              begin
              if( 0 = CompareText( sLabel, TAliasObj( FAliasList.Items[ iCount ]).FLabel ))
              then begin
                   Result:= TAliasObj( FAliasList.Items[ iCount ]).FValue;
                   Break;//of for
                   end;//of if
              end;//of for
            end;//of if
       end;//of if
end;//of function

//------------------------------------------------------------------------------
function TAliasComboBox.GetLabelForAlias( sAlias: String ): String;
var
  iCount: Integer;
begin
  Result := '';
  sAlias := Trim( sAlias );
  if( '' <> sAlias )
  then begin
       if( not Assigned( FAliasList ))
       then Result := sAlias
       else begin
            for iCount := 0 to FAliasList.Count - 1 do
              begin
              if( 0 = CompareText( sAlias, TAliasObj( FAliasList.Items[ iCount ]).FValue ))
              then begin
                   Result:= TAliasObj( FAliasList.Items[ iCount ]).FLabel;
                   Break;//of for
                   end;//of if
              end;//of for
            end;//of else
       end;//of if
end;//of function

//------------------------------------------------------------------------------
function TAliasComboBox.GetItemAlias: String;
begin
  if( 0 > ItemIndex )
  then Result := ''
  else Result := GetAliasForLabel( Items.Strings[ ItemIndex ] );
end;//of function

//------------------------------------------------------------------------------
procedure TAliasComboBox.SetItemAlias( sAlias: String );
var
  bDoChg: Boolean;
  sLabel: String;
  iIndex: Integer;
begin
  if( 0 > ItemIndex )
  then bDoChg:= True
  else if( ItemAlias <> sAlias )
  then bDoChg:= True
  else bDoChg:= False;

  if( bDoChg )
  then begin
       iIndex:= Items.IndexOf( GetLabelForAlias( sAlias ));
       if( 0 > iIndex )
       then //Do nothing
       else begin
            ItemIndex := iIndex;
            Text := Items[ iIndex ];
            end;//of else
       end;//of if
end;//of procedure

//------------------------------------------------------------------------------
procedure TAliasComboBox.AddSingleItemVal( sValue: String );
var
  iPos: Integer;
begin
  iPos := Pos( Items.NameValueSeparator,
               sValue );
  if( 0 < iPos )
  then AddAliasItem( Trim( Copy( sValue, 1, iPos - 1 )),
                     Trim( Copy( sValue, iPos + 1, Length( sValue ) - iPos )))
  else AddAliasItem( Trim( sValue ),
                     Trim( sValue ));
end;//of procedure

//------------------------------------------------------------------------------
procedure TAliasComboBox.AddItem( Item: String; aObject: TObject );
begin
  inherited AddItem( Item, aObject );

  AddSingleItemVal( Item );
end;//of procedure

//------------------------------------------------------------------------------
procedure TAliasComboBox.SetItems( const Value: TStrings );
begin
  AddAliasStrings( Value );
end;//of procedure

end.

Geändert von MiniMatrix ( 1. Aug 2014 um 12:01 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#6

AW: TComboBox mit Aliaswerten

  Alt 31. Jul 2014, 18:56
Den Label-Text packst du in die ComboBox in der gleichen Reihenfolge wie in der Liste und der ItemIndex zeigt dir das Objekt in der Liste.
Wenn jetzt sortiert werden soll, dann sortierst du die Liste und fängst von vorne an (Label-Text in ComboBox)
Oder in das Data-Property (Objects) kommt der Listen-Index.


PS: Sowas nennen viele eine LookupComboBox und die gibt es schon fertig. (in Delphi selber allerdings nur in der datensensitiven Variante)
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#7

AW: TComboBox mit Aliaswerten

  Alt 31. Jul 2014, 19:15
Kennt jemand eine Combobox Komponente, die genau so was kann?
TRzCombobox aus den Raize Components hat dafür eine Values property, in die man die eigentlichen Datenwerte schreibt. Diese korrespondieren dann mit den sichtbaren Items-Werten. Das müsste so ungefähr das sein, was du suchst.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:05 Uhr.
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