Split Button UserControl - integration with RadGrid OnItemCommand

2 posts, 0 answers
  1. Thad
    Thad avatar
    106 posts
    Member since:
    Sep 2010

    Posted 01 Apr 2013 Link to this post

    Hello community!

    I've wrapped a RadButton and RadContextMenu into a server user control and am trying to find out if it is possible to integrate the usercontrol with a RadGrid so that when a RadMenuItem is clicked it can fire the RadGrid_OnItemCommand event just like clicking on a RadButton would do...

    My goal is to catch the server side click event of the RadMenuItem and invoke the click event of the RadButton, thereby fooling the RadGrid into using the CommandName and CommandArgument passed along in a CommandEventArgs object.

    This is how the control is added to the HTML markup:
    <telerik:GridTemplateColumn HeaderText="Actions" HeaderStyle-Width="125px" ItemStyle-Width="125px">
            <fmh:ActionButton runat="server" CommandArgument='<%# Eval("FieldId") %>' ID="abGridTest"
                OnMenuItemClicked="abGridTest_OnMenuItemClicked" >
                    <fmh:ActionItem Text="Example 1" Icon="save" CommandName="test1" />
                    <fmh:ActionItem IsSeparator="true" />
                    <fmh:ActionItem Text="Example 2" Icon="edit" CommandName="test2" />

    Here is a stripped down version of my user control that just does the basics:
    public class ActionItem
        public ActionItem()
            Visible = true;
        public bool IsSeparator { get; set; }
        public bool Visible { get; set; }
        public string CommandName { get; set; }
        public string Icon { get; set; }
        public string Text { get; set; }
    public sealed class ActionButton : DataBoundControl, INamingContainer
        public ITemplate ContentTemplate { get; set; }
        [Bindable(true), DefaultValue("")]
        public string CommandArgument
                object o = ViewState[ClientID + "_CommandArgument"];
                return o == null ? "0" : o.ToString();
            set { ViewState[ClientID + "_CommandArgument"] = value; }
        [MergableProperty(false), PersistenceMode(PersistenceMode.InnerProperty), DefaultValue((string)null)]
        public Collection<ActionItem> ActionItems { get; set; }
        public event CommandEventHandler MenuItemClicked;
        public RadContextMenu ContextMenu { get; set; }
        public RadButton Button { get; set; }
        protected override void CreateChildControls()
            if (ContentTemplate != null)
            if (ActionItems != null)
                foreach (ActionItem actionItem in ActionItems)
                    RadMenuItem rmi = new RadMenuItem();
                    SetupMenuItem(actionItem, rmi);
                    rmi.PostBack = true;
                    rmi.Visible = actionItem.Visible;
        private void ContextMenuOnItemClick(object sender, RadMenuEventArgs radMenuEventArgs)
            CommandEventArgs commandEventArgs = new CommandEventArgs(radMenuEventArgs.Item.Attributes["CommandName"], CommandArgument);
            // This is what I *thought* I would need to do, but this isn't working. Wrong binding flags?
            //typeof (RadButton).InvokeMember("Click", BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, Button,
            //new object[] {commandEventArgs});

    // This works just fine...because I have a reference to the event already
                new CommandEventArgs(radMenuEventArgs.Item.Attributes["CommandName"], CommandArgument));
        private void SetupButtonAndContextMenu()
            Button = new RadButton
                ID = "Button",
                CssClass = "Secondary Utility",
                EnableSplitButton = true,
                Text = @"Action",
                AutoPostBack = false,
                OnClientClicked = "$F.ActionButton.onClientClicked",
                EnableEmbeddedSkins = false,
                Skin = "OurSkin",
                Width = Width
            Button.Icon.SecondaryIconUrl = "/Common/Images/ButtonIcons/DropDownArrow.png";
            ContextMenu = new RadContextMenu
                ID = "Button_Menu",
                ExpandDelay = 0,
                CollapseDelay = 0,
                EnableEmbeddedSkins = false,
                Skin = "OurSkin",
                OnClientItemClicked = "$F.ActionButton.onClientMenuItemClicked"
            ContextMenu.ItemClick += ContextMenuOnItemClick;
        private static void SetupMenuItem(ActionItem actionItem, RadMenuItem rmi)
            if (actionItem.IsSeparator)
                rmi.IsSeparator = true;
            if (String.IsNullOrEmpty(actionItem.Text))
                throw new ArgumentNullException("Text", @"ActionItem.Text is a required argument.");
            rmi.Text = actionItem.Text;
            if (!String.IsNullOrEmpty(actionItem.Icon))
                rmi.ImageUrl = "/Common/Images/LinkButtonIcons/" + actionItem.Icon + ".png";
            rmi.Attributes["CommandName"] = !String.IsNullOrEmpty(actionItem.CommandName)
                                                ? actionItem.CommandName
                                                : actionItem.Text.RemoveSpaces();

    Hopefully someone will have an insight for me, or if nothing else you can use what I have so far to some benefit...


    PS:  Here is the JavaScript.  I didn't clean it up so it has a bit of functionality you don't notice above.
    $F.ActionButton = {
        onClientClicked: function (sender, eventArgs) {
            // Find the context menu and remove animations
            var contextMenu = window.$find(sender.get_id() + '_Menu');
            // Remove the animation so that it shows/hides immediately
            // If it is already visible, just hide it.  For some reason the contextMenu.get_visible() returns false, hence the dom check.
            if (contextMenu.get_contextMenuElement().style.display == 'block') {
            // get the position of the Button that was clicked
            var currentLocation = window.$telerik.getBounds(sender.get_element());
            // Calculate position to show the context menu
            var contextMenuLeft = currentLocation.x;
            if (contextMenu.get_attributes().getAttribute('RTL') == 't') {
                var contextMenuWidth = $('#' + contextMenu.get_element().id + '_detached').width();
                if (contextMenuWidth == 0) {
                    // reposition off screen so we can calculate the width.  Can't do that until it has been rendered once.
                    contextMenu.showAt(-1000, -1000);
                    contextMenuWidth = $('#' + contextMenu.get_element().id + '_detached').width();
                contextMenuLeft = currentLocation.x + currentLocation.width - contextMenuWidth;
            var contextMenuTop = currentLocation.y + currentLocation.height;
            // Show the context menu
            contextMenu.showAt(contextMenuLeft, contextMenuTop);
        onClientMenuItemClicked: function (sender, eventArgs) {
            // Is there a function defined?
            var clientFunction = eventArgs.get_item().get_attributes().getAttribute("ClientFunction");
            if (!clientFunction || clientFunction.trim() == '') return;
            // Is this a real function?
            var fn = eval(clientFunction);
            if (!fn) return;
            // Build arguments to pass including command name and command argument
            var args = new Object;
            args.commandName = eventArgs.get_item().get_attributes().getAttribute("CommandName");
            args.commandArgument = eventArgs.get_item().get_attributes().getAttribute("CommandArgument");
            // Fire off the function passing arguments
            fn(sender, args);

  2. Danail Vasilev
    Danail Vasilev avatar
    1502 posts

    Posted 04 Apr 2013 Link to this post

    Hi Thad,

    Note that you cannot trigger a button click as well as fire the ItemCommand on the server. You can, however, click the button on the client-side, which in turn will fire the ItemCommand. You can also access the target value from the ItemClick of the RadMenu. The Grid - AJAX-enabled Context Menu online demo will spread more light on how to do that.

    If the above demo, does not help, could you please give more information about the values you want to access from the ItemCommand, as well as provide more details why do you need to fire the ItemCommand event?

    Danail Vasilev
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
Back to Top