4
votes

I am developing a powerpoint addin and using the ribbon designer to do this. I have a gallery item which contains RibbonDropDownItems. I cannot find a way to add click listeners in there, since RibbonDropDownItem Interface does not have a 'Click' event like the RibbonButton Interface.

So, is there a way to catch a click event from a RibbonDropDownItem?


EDIT: Implementing the addin for office 2013-2016

3

3 Answers

1
votes

You need to subscribe to the SelectionChanged event of the RibbonDropDown control. It is fired when a user selects a new item on a Ribbon drop-down control. Note, the SelectionChanged event is raised only when the selected item changes, and not in the following circumstances:

  • When the user selects the item that was already selected.
  • When a user clicks a button.
  • When you assign a new value to the SelectedItem or SelectedItemIndex properties in your code.

Finally, you can read more about the Fluent UI controls in the following series of articles in MSDN:

1
votes

I have found a solution without going to the XML approach.

The RibbonGallery class (which contains my RibbonDropDownItems) provides the click event which "Occurs when a user clicks an item on this RibbonGallery".

So you could use the RibbonGallery click listener to identify that one of the items was clicked and then retrieve the selected item with the RibbonGallery#SelectedItem. Here is an example:

private void myDropdownGallery_Click(object sender, RibbonControlEventArgs e)
{
    //'ribbonGalleryObject' is the object created in Ribbon.Designer.cs
    RibbonDropDownItem item = ribbonGalleryObject.SelectedItem;

    string itemLabel = item.Label;

    if (itemLabel == "myItem1") {
        System.Windows.Forms.MessageBox.Show("Item 1 says hello");
    }
    else if (itemLabel == "myItem2"){
        System.Windows.Forms.MessageBox.Show("Item 2 says hello");
    }
}

Furthermore, you could rely on reflection to distinguish the RibbonDropDownItems event handlers and keep your architecture similar as the current one.

private void gallery1_Click(object sender, RibbonControlEventArgs e)
{
    //'ribbonGalleryObject' is the object created in Ribbon.Designer.cs
    RibbonDropDownItem item = ribbonGalleryObject.SelectedItem;

    string itemLabel = item.Label;
    string methodName = itemLabel + "_Click";

    System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName);
    methodInfo.Invoke(this, null);
}

//click event handler for item 1
public void myItem1_Click()
{
    System.Windows.Forms.MessageBox.Show("Item 1 says hello");
}

//click event handler for item 2
public void myItem2_Click()
{
    System.Windows.Forms.MessageBox.Show("Item 2 says hello");
}

Note that you should be careful with the reflection approach because there is a "hidden" dependency between the item label and the item event handler name.

0
votes

I have an approach which I find to be easy and gets the job done. To prepare, on the RibbonBar add a RibbonGallery object. This object has two collections, one for RibbonButtons and another collection for "Items". The latter is what this question was asking about. To prepare for this, this RibbonGallery gets a Click handler and I created a handler specific to this RibbonGallery. When an item (from the second Items collection) gets chosen, it fires this event:

private void Handler_ItemClick( object sender, RibbonControlEventArgs e )
{
    try
    {
        String tag = GALLERY_FOR_THIS_SET_OF_ITEMS.SelectedItem.Tag;
        if (tag != null)
        {
            // use the tag to identify which "Item" it is. 
            // You also get access to other fields in the Item object
            // such as the name/id/label of the Item.
        }
    }
    catch (Exception)
    { }
}

The StackOverflow question asked about menu items and this was a simple method to do that.

As a related extra, what if you had chosen the first collection, which is a collection of RibbonButtons? RibbonButtons are easier to work with. You can use a generic handler as follows:

private void RibbonButtonHandler_Click( object sender, RibbonControlEventArgs e )
{
    try 
    {
            String tag = null;
            RibbonButton b = (RibbonButton)sender;              
            // Now that you have the button, you know what they wanted.
            tag = b.Tag;
            if ( tag != null )
            {
            }
    }
    catch( Exception )
    { }
}