开发者

What is the purpose of the 'Tag' property of Delphi VCL components?

Is there any specific purpose for the 'Tag' property of Delphi VCL components? I have Googled a few examples using it as, for example, a 'color' property or using the 开发者_C百科value as a pointer address, but is it 'good practice' to use it, or is it considered 'bad practice' as it ties the program logic to the UI?


The "tag" property is there as a "cargo container" for whatever you might want to do with it.

Something it's often used for is in event handlers when you have a lot of similar components sharing one event handler. The event handler can find its caller and then query its tag value to get some more information about what it's supposed to be acting on.

EDIT:

Example: A calculator app might tag the number buttons with their respective numbers... silly and incomplete example, but you get the idea. The event handler could then pull the number to add into the display and accumulator right out of the tag instead of having to go figure out which button is meant to do what.


It is a place to add a piece of information to any component, even if you don't have the source for that component. It should be used carefully, because you can use it for only one purpose per component. For that reason Libraries should never use it.


I have some fundamental problems with the Tag property. Well not exactly this property itself because it works as intended.

In general I consider using any universal/general/multi-purpose variables as a 'bad practice'. They can be useful during debugging but are very harmful in production/mission critical environment. They reduce code readability and understandability because nobody knows what a 'Tag' named attribute or property does. Of course you know why you are using this variable. But sooner or later you will forget (I know you will) and relying on this value makes anything more complicated. This is why we should properly name every variable and property to help us understand what the code does.

Using Tag property is just a workaround/shortcut to avoid implementing understandable and well written code. This is the PRACTICE and it is addictive. Next time you need to store a new integer value bound to a component you will use the Tag property without considering any other way to store the desired values. And storing a pointer in Tag property is a horrible idea: you have to cast this value every time you debug pointers.

Tell me: how many times did you find yourself in a situation where you wanted to store a new value in the Tag property but you realized this property is already used for a different purpose (if only there would be a 'Tag2' property in every component...).


As others have said, it's a place to put anything. Typically this comes in handy when associating two objects via an object reference or pointer. The tag happens to be perfectly sized to hold a pointer, so if you need to, say, keep an object tied to an item in a listbox, it becomes pretty straightforward.


Also it can be used for grouping purposes, say you'd want to access all components with a specific tag value, regardless of the component's type.


It's great! A freebie. I use it all the time to store one additional piece of information associated with the object.

Often I store a pointer to an associated data structure, or sometimes an integer which may be an index into some other array.

You can use it as a counter for times the object is accessed, or whatever.

The only downside is if your program uses lots of memory and you have millions of objects, those 4 bytes for each tag add up, especially if you're not using it. In that case, for your most prolific object type, you may want to create your own version without the tag.


You have 2 buttons on your form, on one you set the Tag = 1, and the other one Tag = 2. Now you assign the same OnClick event to both buttons and writhe the code like this:

procedure TForm28.Button1Click(Sender: TObject);
begin
  case (Sender as TButton).Tag of
   1: Caption := 'you pressed button 1';
   2: Caption := 'you pressed button 2';
  end;
end;

or more compact:

procedure TForm28.Button1Click(Sender: TObject);
begin
  Caption := 'you pressed button ' + IntToStr((Sender as TButton).Tag);
end;

Basically,Tag will let you identify what control fired the event. Think if you have a form with dynamically created buttons... a list with users from the database, and on each record you put a button "Delete User". In this situation you can't create an event for each button, you will create one event that will assigned to all the buttons... and you can put in the Tag the userid for example. That way when you implement the event to handle all the buttons, you'll know what user to delete.


I Use tags all the time. here are some examples;

a simple sample: you have a notebook (Like a pagecontroll without tabs) so you can define buttons as tabs and write

NoteBook.ActivePage := TButton(Sender).Tag;

A more complicated sample; an integer can hold 16 bitwise bolleans; I can then check the senders up to 16 conditions to decide how to continue the pricedure

If (BitCheck (Bit2,TButton(sender).tag=True) And BitCheck(bit12,TButton(Sender).Tag=False) Then
Begin
end;

If (BitCheck (Bit9,TButton(sender).tag=True) Or BitCheck(bit14,TButton(Sender).Tag=True) Then
Begin
end;

You Get the idea

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜