Tuesday, February 14, 2012

Right Click contextMenu Problem in Flex 4

Pretty recently I got a requirement of right-click menu (context menu) for every item-renderer in my Spark List. I just got the idea from:
http://blog.flexexamples.com/2010/05/06/setting-a-custom-context-menu-on-a-spark-list-control-item-renderer-in-flex-4/

Pretty cool h?Nope. When I wrote my code it did not work. I checked out lots of reference about it and reached to this page:
http://stackoverflow.com/questions/5220411/flex4-right-click-spark-list-using-contextmenu

At the last it gave a link to adobe page:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/ui/ContextMenu.html

When I followed up this page I noticed the following:
In Flex or Flash Builder, only top-level components in the application can have context menus. For example, if a DataGrid control is a child of a TabNavigator or VBox container, the DataGrid control cannot have its own context menu.

I checked out my code and noticed that my list was in scroller which was in a group and that was in a Spark panel.

Panel
   Scroller
     Group
            List
      Group
   Scroller
Panel




I was adding the context-menu in the item renderer and was totally confused what to do. I keep on following different blogs but all repeat what adobe-help page was stating. Then I played up with the example taken from flexexamples blog.

I noticed one thing that when I replace Panel with BorderContainer my contextMenu was working :O But when I tried to create some skin and assign that skin to this BorderContainer, again the same problem.

After a lot of browsing here and there, I came to know that this is a bug with Spark panel and TitleWindow. Shocking :O

So the workaround for this is:

  1. set mouseEnabled=true in Panel
  2. create a custom skin which inherits from spark.skins.spark.PanelSkin
  3. set mouseEnabled=true in the created custom skin
Setting the mouseEnabled property and the custom Skin can be easily achieved in mxml:
<
s:Panel mouseEnabled="true" skinClass="demo.style.NewPanelSkin"
/>



Developers who define their panel in ActionScript have to remember that skinClass is a style and not a property:
var panel:Panel = new Panel();
panel.mouseEnabled = true;
panel.setStyle("skinClass", NewPanelSkin);
The custom skin itself does nothing else than setting the mouseEnabled property to true:
package demo.style
{
  import spark.skins.spark.PanelSkin;
 
  public class NewPanelSkin extends PanelSkin
 {
    override public function NewPanelSkin()
    {
      super();
      mouseEnabled = true;
    }
  }
}

And then we are ready to go :). This bug made me spend so many hours. I hope it will be helpful for somebody at least.

Also Check

7 comments:

rajul.urvashi said...

Thanks Akhil for sharing this.

Akhil said...

Thanks Rajul.urvashi. Hope it will help others :)

Anonymous said...

Definitely helped! I wasn't aware of this, and had spent a considerable amount of time wondering why my code wasn't working! Thanks for posting this...

Akhil Mittal said...

Your Welcome Mr Anonymous :)

David said...

Life saver! Thanks!

zhanna said...

Thanks a lot! Finally it worked! BUT, I cannot get rid of builtin items

Akhil Mittal said...

David: Welcome.

Zhanna: We have method to hide built-in items. But I think we cannot hide all of them. You will have to go with them.