Add an item click listener directly to dynamically populated context menu in code behind









up vote
0
down vote

favorite












I have a context menu in WPF which will be driven by a List<String> to display a dynamically generated set of menu items.



The list is assigned to the ItemsSource property of the context menu, and correctly displays the content of the menu.



It I create a MenuItem in code behind, I can assign a click listener to the item, and then add that item to the Items list of the menu which correctly populates the list, and allows each item to call the click listener.



I have implemented this approach as shown below.



 private ContextMenu _elementContextMenu;

public ContextMenu ElementContextMenu
get
if (_elementContextMenu == null)
_elementContextMenu = new ContextMenu();

//root menu item
_elementMenuRootItem = new MenuItem();
_elementMenuRootItem.Click += _elementMenuRootItem_Click;
_elementMenuRootItem.ItemsSource = ElementMenuContent;

_elementContextMenu.Items.Add(_elementMenuRootItem);

return _elementContextMenu;

set _elementContextMenu = value;



Using that approach, the click listener passes the clicked menu item as the source of the event, and I can cast it to a MenuItem as shown below:



 void _elementMenuRootItem_Click(object sender, RoutedEventArgs e) 
MenuItem selectedMenuItem = (MenuItem)e.OriginalSource;



What I want to achieve is a list of items which show up as the root of the list.



If I bind the list of menu items (name ElementMenuContent in this implementation) to the ItemsSource property of the context menu, the menu is populated as I would like it to be, however there is no Click event in the ContextMenu.



The desired implementation is shown below:



 public ContextMenu ElementContextMenu 
get
if (_elementContextMenu == null)
_elementContextMenu = new ContextMenu();
_elementContextMenu.ItemsSource = ElementMenuContent;

//Add a click listener directly to the ContextMenu object which allows
//the source menu item which was clicked to be referenced in the same way
//as with a MenuItem click listener

return _elementContextMenu;

set _elementContextMenu = value;



The component this is being implemented in extends the WPF Canvas, and is a .cs file only, so this must be implemented entirely in code. I cannot use XAML in this case.



Any help would be appreciated.










share|improve this question

























    up vote
    0
    down vote

    favorite












    I have a context menu in WPF which will be driven by a List<String> to display a dynamically generated set of menu items.



    The list is assigned to the ItemsSource property of the context menu, and correctly displays the content of the menu.



    It I create a MenuItem in code behind, I can assign a click listener to the item, and then add that item to the Items list of the menu which correctly populates the list, and allows each item to call the click listener.



    I have implemented this approach as shown below.



     private ContextMenu _elementContextMenu;

    public ContextMenu ElementContextMenu
    get
    if (_elementContextMenu == null)
    _elementContextMenu = new ContextMenu();

    //root menu item
    _elementMenuRootItem = new MenuItem();
    _elementMenuRootItem.Click += _elementMenuRootItem_Click;
    _elementMenuRootItem.ItemsSource = ElementMenuContent;

    _elementContextMenu.Items.Add(_elementMenuRootItem);

    return _elementContextMenu;

    set _elementContextMenu = value;



    Using that approach, the click listener passes the clicked menu item as the source of the event, and I can cast it to a MenuItem as shown below:



     void _elementMenuRootItem_Click(object sender, RoutedEventArgs e) 
    MenuItem selectedMenuItem = (MenuItem)e.OriginalSource;



    What I want to achieve is a list of items which show up as the root of the list.



    If I bind the list of menu items (name ElementMenuContent in this implementation) to the ItemsSource property of the context menu, the menu is populated as I would like it to be, however there is no Click event in the ContextMenu.



    The desired implementation is shown below:



     public ContextMenu ElementContextMenu 
    get
    if (_elementContextMenu == null)
    _elementContextMenu = new ContextMenu();
    _elementContextMenu.ItemsSource = ElementMenuContent;

    //Add a click listener directly to the ContextMenu object which allows
    //the source menu item which was clicked to be referenced in the same way
    //as with a MenuItem click listener

    return _elementContextMenu;

    set _elementContextMenu = value;



    The component this is being implemented in extends the WPF Canvas, and is a .cs file only, so this must be implemented entirely in code. I cannot use XAML in this case.



    Any help would be appreciated.










    share|improve this question























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I have a context menu in WPF which will be driven by a List<String> to display a dynamically generated set of menu items.



      The list is assigned to the ItemsSource property of the context menu, and correctly displays the content of the menu.



      It I create a MenuItem in code behind, I can assign a click listener to the item, and then add that item to the Items list of the menu which correctly populates the list, and allows each item to call the click listener.



      I have implemented this approach as shown below.



       private ContextMenu _elementContextMenu;

      public ContextMenu ElementContextMenu
      get
      if (_elementContextMenu == null)
      _elementContextMenu = new ContextMenu();

      //root menu item
      _elementMenuRootItem = new MenuItem();
      _elementMenuRootItem.Click += _elementMenuRootItem_Click;
      _elementMenuRootItem.ItemsSource = ElementMenuContent;

      _elementContextMenu.Items.Add(_elementMenuRootItem);

      return _elementContextMenu;

      set _elementContextMenu = value;



      Using that approach, the click listener passes the clicked menu item as the source of the event, and I can cast it to a MenuItem as shown below:



       void _elementMenuRootItem_Click(object sender, RoutedEventArgs e) 
      MenuItem selectedMenuItem = (MenuItem)e.OriginalSource;



      What I want to achieve is a list of items which show up as the root of the list.



      If I bind the list of menu items (name ElementMenuContent in this implementation) to the ItemsSource property of the context menu, the menu is populated as I would like it to be, however there is no Click event in the ContextMenu.



      The desired implementation is shown below:



       public ContextMenu ElementContextMenu 
      get
      if (_elementContextMenu == null)
      _elementContextMenu = new ContextMenu();
      _elementContextMenu.ItemsSource = ElementMenuContent;

      //Add a click listener directly to the ContextMenu object which allows
      //the source menu item which was clicked to be referenced in the same way
      //as with a MenuItem click listener

      return _elementContextMenu;

      set _elementContextMenu = value;



      The component this is being implemented in extends the WPF Canvas, and is a .cs file only, so this must be implemented entirely in code. I cannot use XAML in this case.



      Any help would be appreciated.










      share|improve this question













      I have a context menu in WPF which will be driven by a List<String> to display a dynamically generated set of menu items.



      The list is assigned to the ItemsSource property of the context menu, and correctly displays the content of the menu.



      It I create a MenuItem in code behind, I can assign a click listener to the item, and then add that item to the Items list of the menu which correctly populates the list, and allows each item to call the click listener.



      I have implemented this approach as shown below.



       private ContextMenu _elementContextMenu;

      public ContextMenu ElementContextMenu
      get
      if (_elementContextMenu == null)
      _elementContextMenu = new ContextMenu();

      //root menu item
      _elementMenuRootItem = new MenuItem();
      _elementMenuRootItem.Click += _elementMenuRootItem_Click;
      _elementMenuRootItem.ItemsSource = ElementMenuContent;

      _elementContextMenu.Items.Add(_elementMenuRootItem);

      return _elementContextMenu;

      set _elementContextMenu = value;



      Using that approach, the click listener passes the clicked menu item as the source of the event, and I can cast it to a MenuItem as shown below:



       void _elementMenuRootItem_Click(object sender, RoutedEventArgs e) 
      MenuItem selectedMenuItem = (MenuItem)e.OriginalSource;



      What I want to achieve is a list of items which show up as the root of the list.



      If I bind the list of menu items (name ElementMenuContent in this implementation) to the ItemsSource property of the context menu, the menu is populated as I would like it to be, however there is no Click event in the ContextMenu.



      The desired implementation is shown below:



       public ContextMenu ElementContextMenu 
      get
      if (_elementContextMenu == null)
      _elementContextMenu = new ContextMenu();
      _elementContextMenu.ItemsSource = ElementMenuContent;

      //Add a click listener directly to the ContextMenu object which allows
      //the source menu item which was clicked to be referenced in the same way
      //as with a MenuItem click listener

      return _elementContextMenu;

      set _elementContextMenu = value;



      The component this is being implemented in extends the WPF Canvas, and is a .cs file only, so this must be implemented entirely in code. I cannot use XAML in this case.



      Any help would be appreciated.







      c# wpf code-behind






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 8 at 18:10









      Alex

      966623




      966623






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          0
          down vote













          I'm not sure I understand this part of your question:




          What I want to achieve is a list of items which show up as the root of the list.




          As you said, there is no Click event available on the ContextMenu itself. The simplest solution would be to instead subscribe to PreviewMouseUp which will capture all mouse click activity and then you can use the MouseButtonEventArgs to access what you need.



          PreviewMouseUp: https://docs.microsoft.com/en-us/dotnet/api/system.windows.uielement.previewmouseup?view=netframework-4.7.2



          If this doesn't help, you can always look into creating a custom routed event: https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/how-to-create-a-custom-routed-event






          share|improve this answer




















          • This was how I first tried to make this work, and it did correctly act on the mouse click, however it didn't allow me to easily get the content of the menu item. The solution I went with in the end was to attach a handler in code behind. This is straightforward in XAML, but not so intuitive with just c# code.
            – Alex
            Nov 9 at 17:32

















          up vote
          0
          down vote













          For anybody stuck on this same issue, the solution is to set the ItemsSource property of the menu itself (in this case, the ElementMenuContent object is a List<String>, and add an event handler to the ContextMenu which operates on the ClickEvent of any MenuItem component as follows:



           _elementContextMenu.ItemsSource = ElementMenuContent;

          _elementContextMenu.AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(ElementContextMenuItemClick));


          The handler method is defined as normal.



           public void ElementContextMenuItemClick(object sender, RoutedEventArgs e) 
          MenuItem selectedMenuItem = (MenuItem)e.OriginalSource;
          String command = selectedMenuItem.Header.ToString();
          SwimLaneController.Instance.ProcessContextMenuCommand(this, command);






          share|improve this answer




















            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53213737%2fadd-an-item-click-listener-directly-to-dynamically-populated-context-menu-in-cod%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            0
            down vote













            I'm not sure I understand this part of your question:




            What I want to achieve is a list of items which show up as the root of the list.




            As you said, there is no Click event available on the ContextMenu itself. The simplest solution would be to instead subscribe to PreviewMouseUp which will capture all mouse click activity and then you can use the MouseButtonEventArgs to access what you need.



            PreviewMouseUp: https://docs.microsoft.com/en-us/dotnet/api/system.windows.uielement.previewmouseup?view=netframework-4.7.2



            If this doesn't help, you can always look into creating a custom routed event: https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/how-to-create-a-custom-routed-event






            share|improve this answer




















            • This was how I first tried to make this work, and it did correctly act on the mouse click, however it didn't allow me to easily get the content of the menu item. The solution I went with in the end was to attach a handler in code behind. This is straightforward in XAML, but not so intuitive with just c# code.
              – Alex
              Nov 9 at 17:32














            up vote
            0
            down vote













            I'm not sure I understand this part of your question:




            What I want to achieve is a list of items which show up as the root of the list.




            As you said, there is no Click event available on the ContextMenu itself. The simplest solution would be to instead subscribe to PreviewMouseUp which will capture all mouse click activity and then you can use the MouseButtonEventArgs to access what you need.



            PreviewMouseUp: https://docs.microsoft.com/en-us/dotnet/api/system.windows.uielement.previewmouseup?view=netframework-4.7.2



            If this doesn't help, you can always look into creating a custom routed event: https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/how-to-create-a-custom-routed-event






            share|improve this answer




















            • This was how I first tried to make this work, and it did correctly act on the mouse click, however it didn't allow me to easily get the content of the menu item. The solution I went with in the end was to attach a handler in code behind. This is straightforward in XAML, but not so intuitive with just c# code.
              – Alex
              Nov 9 at 17:32












            up vote
            0
            down vote










            up vote
            0
            down vote









            I'm not sure I understand this part of your question:




            What I want to achieve is a list of items which show up as the root of the list.




            As you said, there is no Click event available on the ContextMenu itself. The simplest solution would be to instead subscribe to PreviewMouseUp which will capture all mouse click activity and then you can use the MouseButtonEventArgs to access what you need.



            PreviewMouseUp: https://docs.microsoft.com/en-us/dotnet/api/system.windows.uielement.previewmouseup?view=netframework-4.7.2



            If this doesn't help, you can always look into creating a custom routed event: https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/how-to-create-a-custom-routed-event






            share|improve this answer












            I'm not sure I understand this part of your question:




            What I want to achieve is a list of items which show up as the root of the list.




            As you said, there is no Click event available on the ContextMenu itself. The simplest solution would be to instead subscribe to PreviewMouseUp which will capture all mouse click activity and then you can use the MouseButtonEventArgs to access what you need.



            PreviewMouseUp: https://docs.microsoft.com/en-us/dotnet/api/system.windows.uielement.previewmouseup?view=netframework-4.7.2



            If this doesn't help, you can always look into creating a custom routed event: https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/how-to-create-a-custom-routed-event







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 8 at 21:59









            Sirgrowns

            516




            516











            • This was how I first tried to make this work, and it did correctly act on the mouse click, however it didn't allow me to easily get the content of the menu item. The solution I went with in the end was to attach a handler in code behind. This is straightforward in XAML, but not so intuitive with just c# code.
              – Alex
              Nov 9 at 17:32
















            • This was how I first tried to make this work, and it did correctly act on the mouse click, however it didn't allow me to easily get the content of the menu item. The solution I went with in the end was to attach a handler in code behind. This is straightforward in XAML, but not so intuitive with just c# code.
              – Alex
              Nov 9 at 17:32















            This was how I first tried to make this work, and it did correctly act on the mouse click, however it didn't allow me to easily get the content of the menu item. The solution I went with in the end was to attach a handler in code behind. This is straightforward in XAML, but not so intuitive with just c# code.
            – Alex
            Nov 9 at 17:32




            This was how I first tried to make this work, and it did correctly act on the mouse click, however it didn't allow me to easily get the content of the menu item. The solution I went with in the end was to attach a handler in code behind. This is straightforward in XAML, but not so intuitive with just c# code.
            – Alex
            Nov 9 at 17:32












            up vote
            0
            down vote













            For anybody stuck on this same issue, the solution is to set the ItemsSource property of the menu itself (in this case, the ElementMenuContent object is a List<String>, and add an event handler to the ContextMenu which operates on the ClickEvent of any MenuItem component as follows:



             _elementContextMenu.ItemsSource = ElementMenuContent;

            _elementContextMenu.AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(ElementContextMenuItemClick));


            The handler method is defined as normal.



             public void ElementContextMenuItemClick(object sender, RoutedEventArgs e) 
            MenuItem selectedMenuItem = (MenuItem)e.OriginalSource;
            String command = selectedMenuItem.Header.ToString();
            SwimLaneController.Instance.ProcessContextMenuCommand(this, command);






            share|improve this answer
























              up vote
              0
              down vote













              For anybody stuck on this same issue, the solution is to set the ItemsSource property of the menu itself (in this case, the ElementMenuContent object is a List<String>, and add an event handler to the ContextMenu which operates on the ClickEvent of any MenuItem component as follows:



               _elementContextMenu.ItemsSource = ElementMenuContent;

              _elementContextMenu.AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(ElementContextMenuItemClick));


              The handler method is defined as normal.



               public void ElementContextMenuItemClick(object sender, RoutedEventArgs e) 
              MenuItem selectedMenuItem = (MenuItem)e.OriginalSource;
              String command = selectedMenuItem.Header.ToString();
              SwimLaneController.Instance.ProcessContextMenuCommand(this, command);






              share|improve this answer






















                up vote
                0
                down vote










                up vote
                0
                down vote









                For anybody stuck on this same issue, the solution is to set the ItemsSource property of the menu itself (in this case, the ElementMenuContent object is a List<String>, and add an event handler to the ContextMenu which operates on the ClickEvent of any MenuItem component as follows:



                 _elementContextMenu.ItemsSource = ElementMenuContent;

                _elementContextMenu.AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(ElementContextMenuItemClick));


                The handler method is defined as normal.



                 public void ElementContextMenuItemClick(object sender, RoutedEventArgs e) 
                MenuItem selectedMenuItem = (MenuItem)e.OriginalSource;
                String command = selectedMenuItem.Header.ToString();
                SwimLaneController.Instance.ProcessContextMenuCommand(this, command);






                share|improve this answer












                For anybody stuck on this same issue, the solution is to set the ItemsSource property of the menu itself (in this case, the ElementMenuContent object is a List<String>, and add an event handler to the ContextMenu which operates on the ClickEvent of any MenuItem component as follows:



                 _elementContextMenu.ItemsSource = ElementMenuContent;

                _elementContextMenu.AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(ElementContextMenuItemClick));


                The handler method is defined as normal.



                 public void ElementContextMenuItemClick(object sender, RoutedEventArgs e) 
                MenuItem selectedMenuItem = (MenuItem)e.OriginalSource;
                String command = selectedMenuItem.Header.ToString();
                SwimLaneController.Instance.ProcessContextMenuCommand(this, command);







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 9 at 17:29









                Alex

                966623




                966623



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53213737%2fadd-an-item-click-listener-directly-to-dynamically-populated-context-menu-in-cod%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

                    Edmonton

                    Crossroads (UK TV series)