EConvertError on assigning a TMenuItem instance to another one

delphi, delphi-xe2

Solution

That is a common error message. Most visual components in Delphi do not override `TPersistent.Assign`. When that method isn't overridden, the default implementation takes over, which simply throws an exception and fills in the class names of the source and target objects. I think it's left unimplemented because it's unclear exactly which properties should be copied, in general, so the decision is left to you, as the programmer.

If you make a descendant of the classes you're using, you can implement `Assign` or `AssignTo` to copy all the properties you want, but it might not be worth the effort. Instead, it's probably easiest to just write a function that does the copying:

procedure AssignMenuItem(Target, Source: TMenuItem);

For menus and buttons, the best solution is to use `TAction`. Assign the action's caption, icon, help ID, and event handlers, and then associate that action with all the buttons and menu items that need to have the same behavior. They can all share the same action. Changes to the action's properties at run time will be automatically reflected in the associated visual controls.

Problem

In one of my applications, a drop down menu and a popup menu share some menu items (which are built dynamically), so I thought I could add the `TMenuItem` instance to both menus using this code: ``` MI := TMenuItem.Create(nil); { set MI action } DropDownMenu.Add(MI); PopupMenu.Items.Add(MI); ``` Wrong. I got an `EMenuError` with message Menu inserted twice. Rational, so I changed my code to have two instances of my menu item using this code: ``` MI := TMenuItem.Create(nil); { set MI action } PopupMenu.CreateMenuItem.Assign(MI); DropDownMenu.Add(MI); ``` Wrong again. I'm getting an `EConvertError` with this message: Cannot assign a TMenuItem to a TMenuItem. Am I doing anything wrong?

Original source