是否存在类似TDbComboBox
的控件,它通过固定列表显示其值(用于枚举类型,例如TSomeValueEnum = (svSmall=1, svMedium=2, svLarge=3)
)?
例如:
1=small
2=medium
3=large
在数据库中我保存1或2或3,但在ComboBox中只显示相应的值。
答案 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描述的自定义绘图。