简体   繁体   中英

Run-time manipulation of ValueListEditor rows and values in Delphi

I would like the user to be presented with the following options:

  1. Do something? The answer to this can be Yes or No
  2. How many times? This can be 100, 500, or 1000
  3. Do you want a summary? Again, yes or no.

To do this, I have created a form on which I placed a ValueListEditor with the first columns called Option (in this column I write the questions) and the second column called Selection (which will be Yes/No, 100/500/1000 and Yes/No, respectively).

No obviously, rows 2 and 3 make sense only if the user chooses "yes" in row #1. So I would like to create rows 2 and 3 and provide the corresponding options only if the user has chosen Yes for Row 1.

I have written the following code for this, but it is clearly wrong. By the way, I am new to programming in general, and am finding it really difficult to find a decent book on Delphi. The problem is worsened by the fact that nobody else does any programming of any kind where I am, and so it can get very frustrating - and time-consuming (it took me the better part of a full day yesterday to come up with the following code! I did not even know about ValueListEditor; as I was wading through the strangely organized Tool palette, it looked promising, and so I used it.). Any pointers?

Here is my code (and thanks very much):

procedure TfrmDoSomething.FormCreate(Sender: TObject);
var
  I: integer;
  FirstItemProp, SecondItemProp, ThirdItemProp: TItemProp;
begin
  //add first row
  ValueListEditor1.InsertRow('Do something?', '', True);
  FirstItemProp := TItemProp.Create(ValueListEditor1);
  FirstItemProp.PickList.Add('Yes');
  FirstItemProp.PickList.Add('No');
  ValueListEditor1.ItemProps[0] := FirstItemProp;


//now add the subsequent two rows only if the value for Row#1 is Yes
  if (ValueListEditor1.ItemProps[0] = FirstItemProp.PickList[0]) then
    begin
      ValueListEditor1.InsertRow('Number of times', '', True);
      SecondItemProp := TItemProp.Create(ValueListEditor1);
      SecondItemProp.PickList.Add('100');
      SecondItemProp.PickList.Add('500');
      SecondItemProp.PickList.Add('1000');
      ValueListEditor1.ItemProps[1] := SecondItemProp;

      ValueListEditor1.InsertRow('Summary?', '', True);
      ThirdItemProp := TItemProp.Create(ValueListEditor1);
      ThirdItemProp.PickList.Add('Yes');
      ThirdItemProp.PickList.Add('No');
      ValueListEditor1.ItemProps[2] := ThirdItemProp;
    end;

end;

@KenWhite, thank you. Based on your suggestion of using a ComboBox, I wrote the following code. I guess my problem now is that I am using the wrong event for the CB. My CB is programmatically created fine at run time (By the way, CB1 is declared globally). however, when "yes" is selected, it does not go the second procedure "OnChange", which leads me to think that OnChange is the wrong event. I also tried OnClick and a few more - to no avail. Also, the ShowMessage part in the second procedure is only to test if my choice of event was correct. i will later have to write code to create the other two combo boxes. Thanks.

procedure TfrmCBDoSomething.FormCreate(Sender: TObject);
var
  Label1: TLabel;
begin
  Label1 := TLabel.Create(Self);
  Label1.Align := alLeft;
  CB1 := TComboBox.Create(Self);
  CB1.Parent := Self;
  CB1.Align := alRight;

  Label1.Caption := 'Do Something?';
  Label1.Parent := Self;
  CB1.AddItem('Yes', nil);
  CB1.AddItem('No', nil);
end;


procedure TfrmCBTry.CB1OnChange(Sender: TObject);

begin
  if (CB1.Text = 'Yes') then ShowMessage('Got it!!');
  if (CB1.ItemIndex = 0) then ShowMessage('Got it!!');
  if (Cb1.Items.IndexOf('Yes') = 0) then ShowMessage('Got it!!')
end;

Based on your edit, and using TComboBox (and presuming your question is about the VCL, as you mentioned TValueListEditor and gave no Delphi version):

You need to change the way you're adding items, and then assign the OnChange event in your code.

procedure TfrmCBDoSomething.FormCreate(Sender: TObject);
var
  Label1: TLabel;
begin
  Label1 := TLabel.Create(Self);
  Label1.Align := alLeft;
  CB1 := TComboBox.Create(Self);
  CB1.Parent := Self;
  CB1.Align := alRight;
  CB1.Sorted := False;   // Keep order of items entered

  Label1.Caption := 'Do Something?';
  Label1.Parent := Self;
  CB1.Items.Add('Yes');
  CB1.Items.Add('No');
  // Assign the event handler
  CBI.OnChange := CB1OnChange;

  CB2 := TComboBox.Create(Self);
  CB2.Parent := Self;
  CB2.Items.Add('100');
  CB2.Items.Add('200');
  CB2.Items.Add('500');
  // Position CB2 and add label for second set of options
  // Repeat with CB3 for third set of options
end;

procedure TfrmCBTry.CB1OnChange(Sender: TObject);
begin
  // Enable both CB2 and CB3 if CB1 is 'Yes'
  CB2.Enabled := (CB1.ItemIndex = 0);  // Yes selected
  CB3.Enabled := (CB1.ItemIndex = 0);  
end;

I'm not sure why you're doing all of the above at runtime. This could easily be done in the form designer by just dropping three labels and three comboboxes on a form and setting their properties visually or in the Object Inspector (in the case of the Items or OnChange event, which you would complete the shell of by double-clicking it in the Object Inspector's events tab - that would also assign it to the combobox automatically).

(For future refrence: You should probably have just deleted your original question and asked a new one about TComboBox, or (since you'd received no answers) simply removed the original content of this one and used the info from your edit - AKA second question - as the content instead, so that the question was clear. I've answered only the second question, because it's the only one that has a reasonable answer.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM