How can I modify the WPF ribbon application menu d

2019-06-10 04:28发布

问题:

Is it possible to modify the application menu's drop position for the 10/2010 WPF ribbon? I think it's very unusual that a menu opens at the leftmost position, so I'd like to change that.

Example: in Word 2007 (which - as you probable all know - has the old ribbon design) the application menu opens as far as possible to the right. I'd like to get this behaviour, too, because at the right is the only sensible position for the menu. All its entries are in the left column, which was right below the button then. I've not found any easy way to assign its left position. Does anybody know if and how this is possible?

回答1:

Okay, after many hours of try and error, I found a possible way to do it. It's not the 100% original behaviour like in "Windows 7 Paint" or similar Windows 7 ribbon applications, but in most cases it works.

First, you need to know that the application menu is realized with a Popup, which has a Placement property to define where the popup is opened. You need to override the default behaviour to PlacementMode.Left. This will make the popup menu open up right next to the menu button.

Next, you need to set the Popup.HorizontalOffset property to the negated RibbonApplicationMenu.Width. This is done via Binding and a converter to negate the value.

<r:RibbonApplicationMenu>
    <r:RibbonApplicationMenu.Resources>
        <Style TargetType="Popup">
            <Setter Property="Placement" Value="Left"/>
            <Setter Property="HorizontalOffset" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=r:RibbonApplicationMenu}, Path=Width, Converter={StaticResource ResourceKey=NegateIntegerConverter}}"/>
        </Style>
    </r:RibbonApplicationMenu.Resources>
</r:RibbonApplicationMenu>

The converter is defined in the RibbonWindow.Resources as follows:

<r:RibbonWindow.Resources>
    <local:NegateIntegerConverter x:Key="NegateIntegerConverter"/>
</r:RibbonWindow.Resources>

The localnamespace has to be declared inside of the RibbonWindow:

<r:RibbonWindow x:Class="MainWindow"
    xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
    xmlns:local="clr-namespace:ApplicationRootNamespace"
>

And finally, the code for the NegateIntegerConverter is a class in the application's root namespace:

Public Class NegateIntegerConverter
  Implements IValueConverter

  Public Function Convert(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
    Return -CInt(value)
  End Function

  Public Function ConvertBack(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
    Return -CInt(value)
  End Function
End Class

Class MainWindow

End Class

Now for the difference in behaviour: if the menu cannot fully expand to the right because the screen is ending there, the popup does not simply open up a bit farther to the left, but completely on the left. Maybe I can find out how it's actually behaving like the "Windows 7 Paint" ribbon's menu, but this is a good workaround until then.