We've encountered an issue with the application menu in our program, where the application menu opens in an unexpected location depending where the window is located.
Initially, the application menu would open directly down and to the left of the ribbon's application menu button. We implemented the solution outlined in this question, and that caused the application menu to open in the direction we wanted (down and to the right).
Unfortunately, there's a side effect. As mentioned above, the application menu opens in an unexpected location when the windows is located near the edge of a monitor, though the specifics differ depending upon the screen configuration:
- On a single-monitor system, this will occur when the window is aligned with the screen's right edge.
- On a multi-monitor system, this happens when the window is within 20 pixels of the left edge of any screen except the left-most.
In either case, the application menu will open to the left of the application window, separated from the window by at least 50 pixels.
Below is a stripped-down application that exhibits the above behavior.
The main window:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Custom="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon"
xmlns:Example="clr-namespace:Ribbon_Example"
xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
x:Class="Ribbon_Example.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Ribbon>
<Ribbon.ApplicationMenu>
<RibbonApplicationMenu>
<RibbonApplicationMenu.Resources>
<Example:NegativeIntegerConverter x:Key="NegativeIntegerConverter" />
<Style TargetType="Popup">
<Setter Property="Placement" Value="Left" />
<Setter Property="HorizontalOffset"
Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=RibbonApplicationMenu},
Path=Width,
Converter={StaticResource ResourceKey=NegativeIntegerConverter}}" />
</Style>
</RibbonApplicationMenu.Resources>
<RibbonApplicationMenuItem Header="New..." />
<RibbonApplicationMenuItem Header="Open..." />
<RibbonApplicationMenuItem Header="Close" />
<RibbonApplicationMenuItem Header="Save" />
<RibbonApplicationMenuItem Header="Save As..." />
</RibbonApplicationMenu>
</Ribbon.ApplicationMenu>
</Ribbon>
</Grid>
</Window>
The type converter from the aformentioned question:
using System;
using System.Globalization;
using System.Windows.Data;
namespace Ribbon_Example
{
class NegativeIntegerConverter : IValueConverter
{
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
return -1 * System.Convert.ToInt32( value );
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
return -1 * System.Convert.ToInt32( value );
}
}
}
A picture's worth a thousand words, so here's an example of the multi-monitor version of this problem.
What might we be doing wrong?