TDbLookupComboBox或具有一组固定值的等效控件?

时间:2014-07-27 13:08:52

标签: delphi delphi-2006

是否存在类似TDbComboBox的控件,它通过固定列表显示其值(用于枚举类型,例如TSomeValueEnum = (svSmall=1, svMedium=2, svLarge=3))?

例如:

1=small
2=medium
3=large

在数据库中我保存1或2或3,但在ComboBox中只显示相应的值。

3 个答案:

答案 0 :(得分:3)

Raize Components有一个TRzDbComboBox,你有单独的项目和值列表。

来自帮助:

  

TRzDBComboBox支持Values属性,该属性可用于定义要存储在所选数据库字段中的关联值列表,而不是“项目”列表中维护的字符串值。例如,项目列表可以设置为包含以下项目:Visa,MasterCard,American Express;而值列表将包含以下值:VISA,MC,AMEX。如果用户在下拉列表中选择了American Express项,则AMEX值将存储在数据库表中。

答案 1 :(得分:2)

您可以将TDbLookupComboBox与内存表(fi TClientDataSet)结合使用。使用所需的值填充内存表,TDbLookupComboBox将完成剩下的工作。

但是在数据库中的存储值,UserInterface的字符串表示和应用程序的Enum之间存在一个缺失的链接。要将所有内容放在一个位置,您应该构建一个类,以便在方便安全按代码记录中处理所有这些转换强>方式。

TSomeValueEnum = (svSmall, svMedium, svLarge);

TSomeValue = class
private
  FAsInteger : Integer;
  FAsEnum : TSomeValueEnum;
  FAsString : string;
public
  // returns a new created list with all values
  class function CreateAsList : TObjectList;

  // constructors

  constructor Create( Value : Integer ); overload;
  constructor Create( Value : TSomeValueEnum ); overload;
  constructor Create( const Value : string ); overload;

  // equal comparer with other values    
  function Equals( Obj : TObject ) : Boolean; override;
  function SameValueAs( Other : TSomeValue ) : Boolean;

  // properties
  property AsEnum : TSomeValueEnum read FAsEnum;
  property AsInteger : Integer read FAsInteger;
  property AsString : string read FAsString;

  // Same properties but with different names, just for clarification

  // Value used in Database
  property DbValue : Integer read FAsInteger;
  // Value used for UserInterface
  property UIValue : string read FAsString;
  // Value used inside the applicatiom
  property AppValue : TSomeValueEnum read FAsEnum;
end;

implementation

type
  TSomeValueRec = record
    Int : Integer;
    Str : string;
  end;

// Translation-Array for DbValue and UIValue
const
  C_SomeValues : array[TSomeValueEnum] of TSomeValueRec = ( 
    {svSmall}  (Int:1; Str:'small'), 
    {svMedium} (Int:2; Str:'medium'), 
    {svLarge}  (Int:3; Str:'large') );

function TSomeValue.Equals( Obj : TObject ) : Boolean;
begin
  Result := ( Self = Obj ) or Assigend( Obj ) and (Self.ClassType = Obj.ClassType) and SameValueAs( Obj as TSomeValue );
end;

function TSomeValue.SameValueAs( Other : TSomeValue ) : Boolean;
begin
  Result := ( Self = Other ) or Assigned(Other) and (Self.FAsEnum = Other.FAsEnum);
end;

constructor Create( Value : Integer );
var
  LEnum : TSomeValueEnum;
begin
  inherited Create;
  for LEnum := Low(LEnum) to High(LEnum) do
    if C_SomeValues[LEnum].Int = Value then
      begin
        FAsEnum := LEnum;
        FAsInteger := C_SomeValues[LEnum].Int;
        FAsString := C_SomeValues[LEnum].Str;
        Exit;
      end;  
  raise EArgumentException.CreateFmt('unsupported value %d',[Value]);
end;

constructor Create( const Value : string );
var
  LEnum : TSomeValueEnum;
begin
  inherited Create;
  for LEnum := Low(LEnum) to High(LEnum) do
    if SameText( C_SomeValues[LEnum].Str, Value ) then
      begin
        FAsEnum := LEnum;
        FAsInteger := C_SomeValues[LEnum].Int;
        FAsString := C_SomeValues[LEnum].Str;
        Exit;
      end;  
  raise EArgumentException.CreateFmt('unsupported value "%s"',[Value]);
end;

constructor Create( Value : TSomeValueEnum );
begin
  inherited Create;
  FAsEnum := Value;
  FAsInteger := C_SomeValues[Value].Int;
  FAsString := C_SomeValues[Value].Str;
end;

class function TSomeValue.CreateAsList : TObjectList;
var
  LEnum : TSomeValueEnum;
begin
  Result := TObjectList.Create( True );
  for LEnum := Low(TSomeEnum) to High(TSomeEnum) do
    Result.Add( Self.Create( LEnum ) );
end;

要填充内存表,请从TSomeValue.CreateAsList获取列表并填写该列表中的表格。

答案 2 :(得分:0)

我最终实现了以下解决方法(使用Firebird作为数据库,其他实现将有所不同):

QueryForComboBox.SQL.Text := 
  'SELECT 1 as VAL, ''small'' as TXT FROM RDB$DATABASE'
  + ' UNION ALL SELECT 2 as VAL, ''medium'' as TXT FROM RDB$DATABASE'
  + ' UNION ALL SELECT 3 as VAL, ''large'' as TXT FROM RDB$DATABASE';
//...
ComboBox.KeyField := 'VAL';
ComboBox.ListField := 'TXT';

对于我的小问题,这似乎已经足够了。对于"真实代码"我想,我更喜欢基于TClientDataset的解决方案(如proposed by Sir Rufo

另一种选择是使用TDbComboBox和here描述的自定义绘图。