Search code examples
wpfcontextmenuclipping

ContextMenu clipped in some case


I am currently making a context menu which open from left button click instead of right button click and to do that I inhibit the right click by handling the ContextMenuOpening event like this

private void PinBorder_ContextMenuOpening(object sender, System.Windows.Controls.ContextMenuEventArgs e)
{
    e.Handled = true;
}

and I open the context menu by myself on reaction to the MouseButtonLeftDown event like this :

private void PinBorder_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    PinBorder.ContextMenu.PlacementTarget = PinBorder;
    PinBorder.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Center;
    PinBorder.ContextMenu.HorizontalOffset = 0;
    PinBorder.ContextMenu.VerticalOffset = 0;
    PinBorder.ContextMenu.IsOpen = true;
    e.Handled = true;
}

the problem here is when the ContextMenu is opened the first time everything goes well but if I add an item to the observable collection bound to the context menu and try to reopen it, the context menu is clipped to its previous size (if I try to move the context menu selection with up/down key I can guess that an entry has been created but I can't see it because it is clipped).

I tried to remove the click inhibition stuffs and every thing goes well in that case.

I read about such an issue in .net framework 3.5 but i am targeting 4.0.

Does anyone has a solution ?


Solution

  • If finally found a workaround to get what I want even if this solution must allocate more memory than necessary.

    I recreate the whole contextmenu each time the context menu must open.

    private void PinBorder_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        PropertyInputPin.UpdateCompatibleAdjusters();
    
        PinBorder.ContextMenu = new System.Windows.Controls.ContextMenu();
    
        Binding binding = new Binding("CompatibleAdjusters");
        binding.Mode = BindingMode.OneWay;
        binding.Source = DataContext;
        BindingOperations.SetBinding(PinBorder.ContextMenu, ContextMenu.ItemsSourceProperty, binding);
    
        PinBorder.ContextMenu.PlacementTarget = PinBorder;
        PinBorder.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Center;
        PinBorder.ContextMenu.HorizontalOffset = 0;
        PinBorder.ContextMenu.VerticalOffset = 0;
        PinBorder.ContextMenu.IsOpen = true;
    
        for (int i = 0; i < PropertyInputPin.CompatibleAdjusters.Count; i++)
        {
            MenuItem mi = PinBorder.ContextMenu.ItemContainerGenerator.ContainerFromIndex(i) as MenuItem;
            mi.Click += ContextMenu_Click;
        }
    
        e.Handled = false;
    }