locked
Outlook CommandBarButton click event not fire RRS feed

  • Question

  • Hi all.  I have an Outlook 2007 addin. I need to create buttons dynamically when an event happened. When I create buttons in constructor, all event fires normaly. But when i create buttons from any method which is called from an event outside of class, buttons are created and displayed normally, but they don't fire click events.

    Here is the code:

    private CommandBarPopup _convertToTaskPopup;
            private List<CommandBarButton> _convertToTaskButtonList = new List<CommandBarButton>();
    private Application _application;
     private Explorer _explorer; 
    public OutlookExplorerMonitor(Microsoft.Office.Interop.Outlook.Application application)
            {
                _application = application;
                _explorers = application.Explorers;
                _explorer = application.ActiveExplorer() as Explorer;
                WrapExplorer(_explorer);
            } //Buttons which are created from this method fire click events normally
       private void WrapExplorer(Explorer explorer)
            {
                try
                {
                    if (_explorer != explorer)
                        _explorer = explorer;
                    _wrapper = new OutlookExplorerWrapper(_explorer);
                    _wrapper.Closed += WrapperClosed;
                    _wrappers.Add(_wrapper.Id, _wrapper);
                    _wrapper.SelectionChange += WrapperSelectionChange;
                    if (OOMHelper.GetMajorVersion() != 12) return;
                    CreateMenu(_explorer);
                    DeletePopUps(_explorer);
                    AddButtonToBar(_explorer);
                }
                catch (Exception ex)
                {
                }
            }
    //Creating an CommandBarPopup for buttons
     private void CreateMenu(Explorer explorer)
            {
                try            {
                   
                    CommandBar commandBar;
                    if (!string.IsNullOrEmpty(UserPreferences.Instance.NewTaskButtonCommandBar))
                        commandBar = explorer.CommandBars[UserPreferences.Instance.NewTaskButtonCommandBar];
                    else
                        commandBar = explorer.CommandBars["Standard"];
                  
                    _convertToTaskPopup =
                         (CommandBarPopup)commandBar.Controls.Add(MsoControlType.msoControlPopup, Type.Missing, Type.Missing,
                                                                      3, true);
                    if (_convertToTaskPopup != null)
                    {
                        _convertToTaskPopup.Caption = Resources.Button_CommandBar_ConvertToTask_Caption;
                        _convertToTaskPopup.Tag = Resources.Button_CommandBar_ConvertToTask_Tag;
                        _convertToTaskPopup.BeginGroup = true;
                        _convertToTaskPopup.Visible = true;
                        if (!_convertToTaskPopUps.ContainsKey(_wrapper.Id))
                            _convertToTaskPopUps.Add(_wrapper.Id, _convertToTaskPopup);
                    }
                }
                catch (Exception ex)
                {
                }
            }
    //Creating buttons
      private CommandBarButton newbotton;
       private void CreateConvertPopUpMenu(Explorer explorer, int? index = null, bool visible = true)
            {
                if (OOMHelper.GetMajorVersion() != 12) return;
                try
                {
                    if (_convertToTaskPopup == null) return;
                    newbotton = (CommandBarButton)_convertToTaskPopup.CommandBar.Controls.Add(MsoControlType.msoControlButton, Type.Missing, Type.Missing, Type.Missing, true);
                    newbotton.Caption = " account.AccountName";
                    newbotton.Tag = Guid.NewGuid().ToString() + "accountConvertButton";
                    newbotton.Style = MsoButtonStyle.msoButtonIconAndCaption;
                    newbotton.HelpContextId = 100500;
                    newbotton.Parameter = "Convert";
                    newbotton.Click +=new _CommandBarButtonEvents_ClickEventHandler(ConvertToTask);
                    
                                            }
                        }
                }
                catch (Exception ex)
                {
                }
            }
    //Cleaning menu
       private void DeletePopUps(Explorer explorer)
            {
                try
                {
                    if (explorer == null) return;
                    if (_convertToTaskPopup != null && _convertToTaskPopup.CommandBar != null)
                    {
                        foreach (CommandBarButton button in _convertToTaskPopup.CommandBar.Controls)
                        {
                            button.Delete();
                        }
                    }
                }
                catch(Exception ex)
                {
                }
            }
    //This method executed when an event happens. Buttons which are created from this method do not fire click events.
         [MediatorMessageSink("UpdateUserAccounts")]
            private void UpdateUserAccounts(EventArgs eventArgs)
            {
                try
                {
                    DeletePopUps(_application.ActiveExplorer() as Explorer);
                    CreateConvertPopUpMenu(_application.ActiveExplorer() as Explorer, true);
                }
                catch (Exception ex)
                {
                }
            }
    Can anyone tell me what's happening?
    Thursday, July 18, 2013 1:53 PM

Answers

  • I found the error. This is because this click event was rised in another thread. I have changed UpdateUserAccounts method as follow

      [MediatorMessageSink("UpdateUserAccounts")]
            private void UpdateUserAccounts(EventArgs eventArgs)
            {
                try
                {
                    ThreadPool.QueueUserWorkItem(data =>
                {
                    DeletePopUps(_application.ActiveExplorer() as Explorer);
                    AddButtonToBar(_application.ActiveExplorer() as Explorer, true);
                });
                }
                catch (Exception ex)
                {
                }
            }

    And now it works. Anyway, thank you for your reply.

    • Marked as answer by Quist Zhang Friday, July 19, 2013 9:09 AM
    Friday, July 19, 2013 8:24 AM

All replies

  • Usually when events such as button clicks stop firing it's because the object the handler was added to goes out of scope and is garbage collected. See if that's happening in your case. The button object must be at a scope that won't be garbage collected, and if more than 1 button object is created you need to ensure each instance of the button is staying alive.

    Ken Slovak MVP - Outlook

    Thursday, July 18, 2013 2:23 PM
  • But even when i make my button variable static it gives no result.

    public static CommandBarButton newbotton;

    Friday, July 19, 2013 6:24 AM
  • The only difference between that 2 cases is than in 1-st case the button was created in constructor, and in 2-nd case it was created not in constructor. Can it be the reason? If it so, whats the difference where the button was created?
    Friday, July 19, 2013 6:47 AM
  • I found the error. This is because this click event was rised in another thread. I have changed UpdateUserAccounts method as follow

      [MediatorMessageSink("UpdateUserAccounts")]
            private void UpdateUserAccounts(EventArgs eventArgs)
            {
                try
                {
                    ThreadPool.QueueUserWorkItem(data =>
                {
                    DeletePopUps(_application.ActiveExplorer() as Explorer);
                    AddButtonToBar(_application.ActiveExplorer() as Explorer, true);
                });
                }
                catch (Exception ex)
                {
                }
            }

    And now it works. Anyway, thank you for your reply.

    • Marked as answer by Quist Zhang Friday, July 19, 2013 9:09 AM
    Friday, July 19, 2013 8:24 AM
  • if that is your final form of this method then it is still wrong - all access to any office objects and api must be made on main UI thread.
    Friday, July 19, 2013 12:17 PM