4

Context menu is truncated in different .NET Framework. See images inside ZIP file (there are two screenshots, one from XP and other from Win7).

I created a simple Visual Studio 2010 solution which repro my issue.

( http://www.mediafire.com/download.php?doq7gsh75qgvzwq ).

On XP it seems to work fine, but not on Windows 7.

The issue can be reproduced on Windows 7 if target .NET Framework is 3.5 (including SP1) (please see the image from zip).

If I change the target framework to 4.0 it works fine also on Windows 7.

Is a solution to make context menu full visible in .NET Framework 3.5 on Windows 7 OS ?

Snake Eyes
  • 16,287
  • 34
  • 113
  • 221

3 Answers3

4

It seems that when the ContextMenu is loaded the ScrollContentPresenter for the menu isn't sized correctly, clipping the ItemPresenter of the MenuItems (Below is an abridged version of the visual tree showing the issue).

PopupRoot, Acutal Width: 219,027, Desired Width: 219,027
    Decorator, Acutal Width: 219,027, Desired Width: 219,027
        NonLogicalAdornerDecorator, Acutal Width: 219,027, Desired Width: 219,027
            ContextMenuProxy, Acutal Width: 219,027, Desired Width: 219,027
                SystemDropShadowChrome, Acutal Width: 214,027, Desired Width: 219,027
                    Border, Acutal Width: 214,027, Desired Width: 214,027
                        Grid, Acutal Width: 212,027, Desired Width: 212,027
                            Rectangle, Acutal Width: 28,000, Desired Width: 32,000
                            Rectangle, Acutal Width: 1,000, Desired Width: 31,000
                            Rectangle, Acutal Width: 1,000, Desired Width: 32,000
                            ScrollViewer, Acutal Width: 210,027, Desired Width: 212,027
                                Grid, Acutal Width: 210,027, Desired Width: 210,027
                                    Border, Acutal Width: 210,027, Desired Width: 210,027
                                        ScrollContentPresenter, Acutal Width: 210,027, Desired Width: 210,027
                                            ItemsPresenter, Acutal Width: 241,047, Desired Width: 245,047

Invalidating the measure of the of the ContextMenu's visual root (the PopupRoot) when the menu is loaded should cause the layout to be updated to display the correct bounds for the ItemsPresenter.

The handler for the menu's Load event:

private void mainMenu_Loaded(object sender, RoutedEventArgs e)
{
    if (sender != null)
    {
        ContextMenu menu = sender as ContextMenu;
        if (menu != null)
        {
           // get the visual root for the context menu
           var root = (FrameworkElement)GetVisualTreeRoot(menu);

           // invalidate the menu's layout
           root.InvalidateMeasure();
        }             
    }
}

GetVisualTreeRoot method:

private DependencyObject GetVisualTreeRoot(DependencyObject control)
{
    DependencyObject parent = VisualTreeHelper.GetParent(control);
    if (parent != null)
    {
        return GetVisualTreeRoot(parent);
    }
    else
    {
        return control;
    }
}
Luke Forder
  • 1,179
  • 14
  • 20
  • I awarded you because this is a good workaround. I will try in few days if something works. If yes, the answer will be marked as accepted. Thank you for patience. – Snake Eyes Mar 23 '12 at 14:12
1

A workaround:

<ContextMenu x:Name="mainMenu" Width="300" >

It seems to stop bothering when setting a fixed width. Still a good candidate for Connect.

NestorArturo
  • 2,476
  • 1
  • 18
  • 21
0

I am able to reproduce this issue in .Net 4.5.1 also. Not able to solve using above marked solution as well. InvalidateMeasure still results in empty context menu sometimes and it starts appearing. When I snoop the context menu, found out that menu ItemsPanel size calculation is done fine, but ScrollContentPresenter size is 0.Anyone facing similar issues. My workaround is :

    private static void ContextMenuOnLoaded(object sender, RoutedEventArgs routedEventArgs)
    {
        var menu = (ContextMenu)sender;
        if (menu.HasItems)
        {
            menu.MinHeight = menu.Items.Count * 25;
        }

        menu.Loaded -= ContextMenuOnLoaded;
    }

Not sure if it is the best solution. But why does it happen is also surprising.