Removing context menu item

Vote:
 

I have previously successfully removed items from the edit panel / page context menu. Now I'm trying to do it for the EditTree context menu but the items I remove somehow magically reappear. I've been digging around in reflector but can't figure out where they come from.

I have used the mapping VPP to redirect the EditTree.aspx to use my custom implementation. The original EditTree.aspx inherits EPiServer.UI.Edit.EditTree while I have the hierarchy CustomEditTree.aspx : MyLib.EditTree : EPiServer.UI.Edit.EditTree. Note that CustomEditTree.aspx doesn't have a codebehind, MyLib.EditTree is a class sitting in a different project, if that could matter.

MyLib.EditTree contains this:

protected override void OnPreRender(EventArgs e)
{
    base.OnPreRender(e);

    // Remove change access rights menu item
    if (Menu != null && Menu.Items.Contains("setaccesscaption"))
    {
        Menu.Items.Remove("setaccesscaption");
    }
}

I can step through the code and see that base.OnPreRender results in 10 items being added to Menu.Items (it is empty before this call). I can also see that the "setaccesscaption" does exist and that it is remove, leaving 9 items when the method returns.

But still, all ten items are rendered in the menu. Even if I do Clear() on the collection and verify that it is indeed empty, the context menu will appear the same.

Any hints or suggestions?

Thanks in advance,
Magnus

#42852
Sep 03, 2010 7:47
Vote:
 

You're calling base.OnPreRender() on the EditTree, which calls RegisterRightClickScripts() which in turn unfortunately calls Render() on the RightClickMenu.

One way could be to do a public new RightClickMenuItemCollection Items { get; } and fiddle around with it a bit.

#42944
Sep 07, 2010 14:31
Vote:
 

Yeah, i just saw the Render inside the RegisterRightClickScripts. I've been digging around trying to do it on the client but I couldn't there either. Could you elaborate on your idea with the Items collection? Seems like a good idea, but I don't see how I could get the RegisterRightClickScripts method to behave differently with it.

#42947
Sep 07, 2010 14:49
Vote:
 

I was thinking something like this:

Subclass both EditTree and RightClickMenu, then modify your EditTrees Menu property to return your own implementation of RightClickMenu.

Modify your own implementation of RightClickMenu to exclude "setaccesscaption" (or a list of strings from a nice property :)) from Items.

I haven't tried it, but from looking through Reflector it should work. The alternative would be lots of copy and paste coding, I think. :(

#42948
Sep 07, 2010 15:01
Vote:
 

Had only the RegisterRightClickScripts method used the Menu property and not the _menu field... And RegisterRightClickScripts is itself of course private. How could they make something so simple so hard? :) I guess i could subclass EditTree and divert the call to RegisterRightClickScripts to a method of my own, but I'll have a hard time with the base.OnPreRender call...

#42950
Sep 07, 2010 15:08
Vote:
 

What if you also modify the constructor to initialize _menu to your implementation of RightClickMenu?

And I agree, this feels like a very hacky way to do it... :)

#42951
Sep 07, 2010 15:11
Vote:
 

I can't do that from a subclass because _menu is private.

#42952
Sep 07, 2010 15:12
Vote:
 

You certainly can with reflection!

Type t = typeof(EditTree);
FieldInfo field = t.GetField("_menu", BindingFlags.NonPublic); 
field.SetValue(t, new SuperDuperMenu()); 

Type t = this.GetType();
FieldInfo field = t.GetField("_menu", BindingFlags.NonPublic); 
field.SetValue(t, new SuperDuperMenu()); 

You might have to change the BindingFlags.

#42953
Sep 07, 2010 15:25
Vote:
 

Yeah, but that's a reeeeeally nasty hack :) I might have to though, thanks for the suggestion!

#42954
Sep 07, 2010 15:28
Vote:
 

Bleh, it will work as long as they don't change the name of the private field... :) Good luck!

#42955
Sep 07, 2010 15:30
Vote:
 

Anyone got this working? I'm going insane here!!

#62059
Oct 11, 2012 10:55