That's not really very exciting when you are thinking about spending $400.
Then I watched a video from Code Rage 5 where Ray demonstrates and talks about his components. Wow, did this change my mind. I purchased Raize Components 6.0 three days later. Here is the Code Rage 5 video I'm talking about UI Design with Raize Components.
There's also an XE2 Code Rage 6 video UI Design with Raize Components and RAD Studio XE2
You owe it to yourself to watch one or both of these videos.
Anyway, I have a passion for using Id/Value pairs in all of my lookup code. I find it much easier to pass around an integer Id instead of the actual string value. I guess this comes from years of creating databases with lookup tables based on nonsensical auto-increment Id's. For example:
tblColors
Id | Value |
1 | Blue |
2 | Green |
3 | Red |
4 | Yellow |
So, I was very excited when I learned that the TRzComboBox component from Raize supports Id/Value Pairs. You just right click on the control, choose Edit Items & Values and enter your Id value pairs.
When you want to retrieve the Value associated with the ItemIndex of the control you simply reference the TRzComboBox.Value property.
Okay that was the easy part. Now how do you go about doing the opposite, setting the control so the ItemIndex refletcs the Id value? That's a good question.
Suppose we have the value 7 which represents "Seven" stored in an interger variable and we want to set the control so that Seven is the highlighted item.
You simply iterate through the control testing each of the values to see if it matches. Upon a match you set the ItemIndex.
Raize makes this easy beacause it exposes both the Value property and the Values property. Value corresponds to the ItemIndex and Values is a TStringList of all the values.
Below is a simple little program to demonstrate how to do set the ItemIndex to the Value. It does require Raize Componets 6.0 from http://www.raize.com/
The key is a little helper procedure that accepts two parameters. The first is a TRzComboBox, and the second is the Id value. By passing the TRzComboBox by reference it allows any changes to the ItemIndex to happen directly to the control itself.
Procedure SetComboBoxValue(var cb:TRzComboBox; x:integer); var i :integer; begin for i := 0 to cb.Count - 1 do if x = StrToInt(cb.Values[i]) then begin cb.ItemIndex := i; Exit; end; end;As you can see, it simply iterates through the list of values looking for a match and when found it Exits.
Enjoy,
Semper Fi - Gunny Mike
UPDATE 08/08/2012 9:25 PM EST
I just received an email from Ray Konopka regarding TRzComboBox.Value property. It turns out that the Value property is a read/write property. That means you can assign a value to the Value property and it will change the ItemIndex property automatically! How simple is that...RzComboBox1.Value := IntToStr(7);
Thanks Ray and keep up the great work.
object Form1: TForm1 Left = 0 Top = 0 Caption = 'Form1' ClientHeight = 203 ClientWidth = 226 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object RzButton1: TRzButton Left = 64 Top = 112 Width = 110 Caption = 'Value = 1' TabOrder = 0 OnClick = RzButton1Click end object RzComboBox1: TRzComboBox Left = 64 Top = 32 Width = 110 Height = 21 TabOrder = 1 Text = 'One' OnChange = RzComboBox1Change Items.Strings = ( 'One' 'Two' 'Three' 'Four' 'Five' 'Six' 'Seven' 'One Hundred' 'Nine Nine Nine') ItemIndex = 0 Values.Strings = ( '1' '2' '3' '4' '5' '6' '7' '100' '999') end end
unit SetComboBox; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, RzCmboBx, RzButton; type TForm1 = class(TForm) RzButton1: TRzButton; RzComboBox1: TRzComboBox; procedure RzButton1Click(Sender: TObject); procedure RzComboBox1Change(Sender: TObject); private { Private declarations } public { Public declarations } end; Procedure SetComboBoxValue(var cb:TRzComboBox; x:integer); var Form1: TForm1; implementation {$R *.dfm} Procedure SetComboBoxValue(var cb:TRzComboBox; x:integer); var i :integer; begin for i := 0 to cb.Count - 1 do if x = StrToInt(cb.Values[i]) then begin cb.ItemIndex := i; Exit; end; end; procedure TForm1.RzButton1Click(Sender: TObject); var i,j : integer; begin i := Random(RzComboBox1.Count); j := StrToInt(RzComboBox1.Values[i]); RzButton1.Caption := 'Value = ' + IntToStr(j); SetComboBoxValue(RzComboBox1,j); end; procedure TForm1.RzComboBox1Change(Sender: TObject); begin RzButton1.Caption := 'Value = ' + RzComboBox1.Value; end; end.
It's shorter :)
ReplyDeletecb.ItemIndex := cb.Values.IndexOf(IntToStr(x));
but have to know, that if "x" isn't in Values, then cb.ItemIndex will be -1
XCluster is right and you could do that in a class helper for the raize component.
ReplyDeleteSomething like that:
TRzComboBoxHelper = class helper for TRzComboBox
public
procedure SelectItem(Value: Integer);
end;
procedure TRzComboBoxHelper.SelectItem(Value: Integer);
const
IndexNotFound = -1;
SItemNotFoundError = 'The item "%d" was not found in the list.';
var
FoundedIndex: Integer;
begin
FoundedIndex := Self.IndexOf(Value);
if FoundedIndex = -1 then
Self.ItemIndex := FoundedIndex
else
raise Exception.CreateFmt(SItemNotFoundError, [Value]);
end;
Hope it helps :)
Regards,
Diego Garcia
if FoundedIndex > -1 then
Delete:)
Thanks for the correction xcluster !
DeleteI've quick typed the code here :)
Regards
Diego Garcia
XCluster the right should be:
Deleteif FoundedIndex <> IndexNotFound then
Self.ItemIndex := FoundedIndex
else
raise Exception.CreateFmt(SItemNotFoundError, [Value]);
Regards,
Diego Garcia
And this feature does also work in the TRzDbCombobox, where you can have cryptic values in the database and nice verbose text displayed to the user. Very handy whan you want to have a DB combobox showing its items in the current UI language, while the database content keeps unchanged.
ReplyDeleteVery nice. As a nice side effect the raize components generally fix a lot of weird glitches that I otherwise experienced in the VCL. A simple example is that the Page Control in regular VCL, which is simply a wrapper for the MS Common Controls library does not override the default painting code for Tabs when they are positioned on the bottom. Since Windows itself does a bad job (paints the tabs the wrong way around), and since the VCL doesn't work around it, you have to add owner-draw code to ALL your page controls if you want them to look okay, on Windows Vista or Windows 7 with the tabs positioned at the bottom.
ReplyDeleteWith the Raize page controls (or the Jedi ones, or any other decent tab control), things like this are taken care of for you. And then you can get the funky page/tab shapes that the Raize tab control has. Very nice.
Ray Konopka is a super nice guy and has been a member of the Delphi community since forever. Some of the newcomers might not remember that one of his contributions to the community was the first and only book for Delphi focused on component development. It was for a now-ancient delphi version, but remains the definitive work on the subject. Any aspiring delphi hacker must acquire a copy of his book.
W
I just received an email from Ray Konopka regarding the Value property. As it turns out the Value property is a read/write property. So, you can assign a value to the Value property and the ItemIndex will automatically change. How simple is that.
ReplyDeleteRzComboBox1.Value := IntToStr(7);
Thanks Ray and keep up the great work.
Gunny Mike