I recently fixed worked around a very annoying issue in my code base.
I have a ParentMenuItemBase
abstract class from which I derive classes that essentially wrap a CommandBarPopup
control, and create the child CommandBarButton
objects and wire up their Click
event to execute an ICommand
.
Say I had a RefactorRenameCommand
hooked up to 5 completely independent CommandBarButton
objects, under 5 completely unrelated CommandBarPopup
controls.
When I clicked the CommandBarButton
, the child_Click
handler would then run 5 times - and the Ctrl
parameter would have the same hash code for all 5 "clicks".
Then if I clicked the same button again, the handler would again run 5 times, and again the Ctrl
parameter would have the same hash code for all 5 "clicks", ...but the hash code would be different from what it was the first time around - and if I clicked again, I'd get a new hash code for that parameter.
I obtained the desired behavior by storing the last hash code for that Ctrl
parameter in a private static
field, and only executing the handler if the hash code for Ctrl
was different - in other words, I made it work by building on top of an observed behavior that I didn't completely understand, and it feels dirty and it bothers me beyond words. Here's the hack in question, including the actual in-code comments:
// note: HAAAAACK!!!
private static int _lastHashCode;
private void child_Click(CommandBarButton Ctrl, ref bool CancelDefault)
{
var item = _items.Select(kvp => kvp.Key).SingleOrDefault(menu => menu.Key == Ctrl.Tag) as ICommandMenuItem;
if (item == null || Ctrl.GetHashCode() == _lastHashCode)
{
return;
}
// without this hack, handler runs once for each menu item that's hooked up to the command.
// hash code is different on every frakkin' click. go figure. I've had it, this is the fix.
_lastHashCode = Ctrl.GetHashCode();
Debug.WriteLine("({0}) Executing click handler for menu item '{1}', hash code {2}", GetHashCode(), Ctrl.Caption, Ctrl.GetHashCode());
item.Command.Execute(null);
}
That Debug.WriteLine
call would output something like this:
(46595510) Executing click handler for menu item '&Rename', hash code 16706408 (16139946) Executing click handler for menu item '&Rename', hash code 16706408 (11041789) Executing click handler for menu item '&Rename', hash code 16706408 (32267243) Executing click handler for menu item '&Rename', hash code 16706408 (21969731) Executing click handler for menu item '&Rename', hash code 16706408
And the next click would produce an identical output, except with a different hash code for the Ctrl
parameter.
So, exactly what is this Ctrl
parameter? If it's the CommandBarButton
COM control that was clicked, then why does its hash code not match that of the CommandBarButton
object I created? And why does its hash code change every time the handler runs?