好的,经过数小时的尝试和错误,我找到了一种可行的方法。这不是像“Windows 7 Paint”或类似的 Windows 7 功能区应用程序那样的 100% 原始行为,但在大多数情况下它是有效的。
首先,您需要知道应用程序菜单是用Popup 实现的,它有一个Placement 属性来定义弹出窗口的打开位置。您需要将默认行为覆盖为PlacementMode.Left。这将使弹出菜单在菜单按钮旁边打开。
接下来,您需要将Popup.HorizontalOffset 属性设置为取反的RibbonApplicationMenu.Width。这是通过 Binding 和一个转换器来对值求反。
<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>
转换器在RibbonWindow.Resources中定义如下:
<r:RibbonWindow.Resources>
<local:NegateIntegerConverter x:Key="NegateIntegerConverter"/>
</r:RibbonWindow.Resources>
localnamespace 必须在 RibbonWindow 内声明:
<r:RibbonWindow x:Class="MainWindow"
xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
xmlns:local="clr-namespace:ApplicationRootNamespace"
>
最后,NegateIntegerConverter 的代码是应用程序根命名空间中的一个类:
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
现在来看看行为上的不同:如果菜单不能完全向右展开,因为屏幕在那里结束,弹出窗口不会简单地向左打开一点,而是完全在左侧。也许我可以找出它实际上是如何表现得像“Windows 7 Paint”功能区的菜单,但在此之前这是一个很好的解决方法。