2017-11-21

WPF RibbonSplitButton Activates Twice

On a WPF (Windows Presentation Foundation) RibbonSplitButton there are two parts. There is a button at the top, and a down arrow. The down arrow causes a menu to appear. If you click one of the menu items, there is what I would consider to be a bug, but what Microsoft considers to be "By Design" where it triggers the event code twice. Essentially, it triggers it once for the menu item, and once for the button.

There is a way to handle the problem. Essentially on the first trigger, you need to set the "Handled" property of the RoutedEventArgs to be true. The solution posted on the Microsoft site requires an event handler in code-behind, which isn't compatible with the MVVM architecture. Here is how I handled it using Caliburn.Micro for a button in my application that is supposed to start Excel in one of two different ways. The button at the top executes it with #0, and the two menu items executes it with #1 and #0.

First, here is the XAML. The key part of this is to pass the $executionContext as an argument to the method. This gets the necessary property to where it can be modified.


<ribbon:RibbonSplitButton
 cal:Message.Attach="[Event Click]=[Excel(0, $executionContext)]"
 IsEnabled="{Binding CanExcel}"
 KeyTip="X"
 Label="{x:Static loc:ShellViewResources.Excel}"
 LargeImageSource="/Xoc.MayaCalendar.Windows;component/Assets/Images/Ribbon/ExcelLarge.png"
 SmallImageSource="/Xoc.MayaCalendar.Windows;component/Assets/Images/Ribbon/ExcelSmall.png">
 <ribbon:RibbonMenuItem
  Header="{x:Static loc:ShellViewResources.Excel}"
  ImageSource="/Xoc.MayaCalendar.Windows;component/Assets/Images/Ribbon/PrintSmall.png"
  cal:Message.Attach="[Event Click]=[Excel(1, $executionContext)]" />
 <ribbon:RibbonMenuItem
  Header="{x:Static loc:ShellViewResources.ExcelExample}"
  ImageSource="/Xoc.MayaCalendar.Windows;component/Assets/Images/Ribbon/PrintSmall.png"
  cal:Message.Attach="[Event Click]=[Excel(0, $executionContext)]" />
</ribbon:RibbonSplitButton>

The next part is to handle the event. In the Caliburn.Micro code, it starts with:


public void Excel(ContentLevel contentLevel, ActionExecutionContext executionContext)
{
 RoutedEventArgs routedEventArgs = (RoutedEventArgs)executionContext.EventArgs;
 routedEventArgs.Handled = true;
 // other code
}

This handles the event, which causes it not to cause the second event.

No comments :

Post a Comment