0

I have created a few custom Enumerator-Sets.

Example:

Type TStatus=(Unknown=0, Dead=1, Owned=2, Borrowed=3);

Now I want to fill a Combobox with all the Items defined in my Set. So my fist thought was to use the TypeInfo, GetEnumName and GetEnumValue-Functions.

i:=0;
while GetEnumValue(TypeInfo(TStatus),GetEnumName(TypeInfo(TStatus),i))<>-1 do
begin
  status:=GetEnumName(TypeInfo(TStatus),i);
  ComboBox.Items.Add(status);

  inc(i);
end;

(I tried binding a TStringList to the ComboBox with a seperate Adapter but that didn't work).

After filling my ComboBox I went on to use LiveBindings to bind the property "SelectedValue" to the TStatus-property of my Object, which is simply called Status.

property Status:String read GetStatus write SetStatus;

there are three problems though.

  1. The Combobox shows no Value when I scroll through my Objects even though I assigned a default value to the Status-property.

  2. the Amount of Items in the combobox is:

     Amount of Items in Set + Amount of Objects
    

    So if I have 2 Objects I have 6 Items in my Combobox when it should remain at 4

  3. If I select a Value from the combobox and want to Post it to my Object it doesnt access my Setter-Function.

This whole Live Bindings stuff is still new to me but I'd like to learn it properly.

So if you could help me solve these issues, it would be appreciated.

Thank you for your time.

Edit: My Delphi-Version is 10.1 Berlin and I use VCL, Target Platform is Windows only.

Edit2: https://www.dropbox.com/s/u7znetur723q6i2/DBApp.7z?dl=0 here are my project files.

Viktor Pagels
  • 271
  • 4
  • 15
  • 1
    First off I'd drop the explicit enumerator values, simply use: `type TStatus = (Unknown, Dead, Owned, Borrowed);`. They didn't play well with RTTI at least in the past. – Uli Gerhardt Dec 19 '16 at 06:09
  • I added the numbers specifically for StackOverflow since I am not entirely sure wether it is considered bad practice to not assign values to them. However, I am unfortunately none the wiser. – Viktor Pagels Dec 19 '16 at 10:07
  • I'd say: If you don't need explicit enum values, don't use them. AFAIC they're not idiomatic in Delphi and mainly used for C compatibility (Kylix). – Uli Gerhardt Dec 19 '16 at 10:19
  • Unfortunately I know nothing about live bindings. :-) You might add tags for your Delphi version and whether you use FMX/VCL. – Uli Gerhardt Dec 19 '16 at 10:20
  • I'd like to use these Types later for other Objects as well though. Maybe I should make them into proper classes and implement a state-pattern. but from my project vision that would seem like overkill for what I want to do. I use delphi 10.1 Berlin and VCL, I'll add those infos into the Question. – Viktor Pagels Dec 19 '16 at 10:28
  • I'm not sure if I understand your last comment. You are talking about reusing `TStatus` in other Delphi projects? – Uli Gerhardt Dec 19 '16 at 10:31
  • Not in different Projects but different classes. – Viktor Pagels Dec 19 '16 at 10:59
  • Then there's no problem. `TStatus` is a valid Delphi type either way. – Uli Gerhardt Dec 19 '16 at 11:05
  • I know but my original issues with LiveBindings haven't been resolved yet. – Viktor Pagels Dec 19 '16 at 11:17
  • Yes, but you might want to eliminate known problems. ;-) – Uli Gerhardt Dec 19 '16 at 11:21
  • So far there haven't been any problems with TStatus and comboboxes other than the ones I listed. – Viktor Pagels Dec 19 '16 at 11:51
  • Can you provide your full sample source? It is my instinct that you should be binding to itemIndex, not SelectedValue, but I would like to test first. – Dsm Dec 20 '16 at 09:31
  • sure, but only in around 7h since I am at work right now and my project is on my private laptop. – Viktor Pagels Dec 20 '16 at 10:44
  • No problem. I will look at it tomorrow. – Dsm Dec 20 '16 at 11:03
  • You can download the project from my dropbox account, the link is in the main post – Viktor Pagels Dec 23 '16 at 03:05

1 Answers1

1

I tried a lot of stuff now, including implementation of the State-Pattern.

the property looks now like this:

property Status:String read ReadStatus write SetStatus;

each state has now a constant String which holds the literal-information about what state it is, I called the constant "Statusbez", this is the information that gets passed on to the database now.

function THund.ReadStatus():String;
begin
  if fStatus<>nil then Result:=fStatus.Statusbez;
end;

In order to set a Status I access my TStates-type, which is an enumeration type of all states I will eventually end up with.

procedure THund.SetStatus(value:string);
var
  tempState:String;
  i:Integer;
begin
  tempState:=fStatus.Statusbez;
  i:=GetEnumValue(TypeInfo(TStates),value);

  fStatus:=ChangeStatus(i);
  if fStatus.Statusbez<>tempState then fUpdated:=True;
end;

the changeStatus function simply decides which state to initialize.

function THund.ChangeStatus(value:Integer):TStatus;
begin
  fStatus.Free();

  case value of
    Ord(Vorhanden):Result:=nil;
    Ord(Verstorben):Result:=TDead.Create();
    Ord(Schwanger):Result:=nil;
    Ord(Reserviert):Result:=nil;
    Ord(Laeufig):Result:=nil;
    Ord(Verkauft):Result:=nil;
    Ord(Gnadenbrot):Result:=nil;
    else Result:=nil;
  end;
end;

In order to set the State at runtime I had to break the LiveBindings-Principle and use the Combobox's OnCloseUp-Event, the following line takes the Text in the Combobox, parses over my Enumeration-Type, gets the Enumvalue and assigns a State through it.

Hund.Status:=CB_Hund_Status.Items[CB_Hund_Status.ItemIndex];

I am not very happy that I had to resort to the Events of the component but whatever gets the job done I suppose.

anyways, now I can safely use words in my database to examine the state and put my logic behind seperate classes instead of numbers and switch-case statements here and there.

Viktor Pagels
  • 271
  • 4
  • 15