Search code examples
c#wpfcontextmenucontextmenustrip

WPF sending mouse wheel event from ContextMenu to Window


I have a window, on it, i have a button. The button has a context menu:

<Window>
 <ScrollViewer Height="500">
  <Button Height = "2000">
   <Button.ContextMenu>
    <ContextMenu>
     <MenuItem Header="Item1"></MenuItem>
     <MenuItem Header="Item2"></MenuItem>
     <MenuItem Header="Item3"></MenuItem>
    </ContextMenu>
   </Button.ContextMenu>
  </Button>
 </ScrollViewer>
</Window>

Whenever i right click on button, the context menu will be shown. When i move the mouse out of the context menu and scroll the wheel, the scrollViewer doesn't scroll at all. I have tried many ways on mouse leave or mouse enter events but nothing helps. I want the context menu is still showing but the wheel event is sent to the scrollViewer (or window), if i click outside of the contextmenu, it will close normally.

In win-form application, i have the same issue but i can solve it by using ContextMenuStrip as a replacement for ContextMenu. In WPF, looks like no ContextMenuStrip.


Solution

  • Instread of using a ContextMenu, you could use a Popup that looks like a ContextMenu:

    <ScrollViewer Height="500">
        <Button Height="2000">
            <Popup x:Name="popup" Placement="Mouse" StaysOpen="False"
                       xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2">
                <theme:SystemDropShadowChrome Name="Shdw" Color="Transparent" SnapsToDevicePixels="true">
                    <Border Name="ContextMenuBorder" Background="#F5F5F5" BorderBrush="#FF959595" BorderThickness="1" SnapsToDevicePixels="True">
                        <ScrollViewer Name="ContextMenuScrollViewer" Grid.ColumnSpan="2" Margin="1,0"
                                          Style="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type FrameworkElement}, ResourceId=MenuScrollViewer}}">
                            <Grid RenderOptions.ClearTypeHint="Enabled">
                                <Canvas Height="0" Width="0" HorizontalAlignment="Left" VerticalAlignment="Top">
                                    <Rectangle Name="OpaqueRect" Height="{Binding ElementName=ContextMenuBorder, Path=ActualHeight}"
                                                   Width="{Binding ElementName=ContextMenuBorder, Path=ActualWidth}"
                                                   Fill="{Binding ElementName=ContextMenuBorder, Path=Background}"
                                                   SnapsToDevicePixels="True"/>
                                </Canvas>
                                <Rectangle Fill="#F1F1F1" HorizontalAlignment="Left" Width="28" Margin="1,2" RadiusX="2" RadiusY="2" SnapsToDevicePixels="True"/>
                                <Rectangle HorizontalAlignment="Left" Width="1" Margin="29,2,0,2" Fill="#E2E3E3" SnapsToDevicePixels="True"/>
                                <Rectangle HorizontalAlignment="Left" Width="1" Margin="30,2,0,2" Fill="White" SnapsToDevicePixels="True"/>
                                <StackPanel>
                                    <MenuItem Header="Item1"></MenuItem>
                                    <MenuItem Header="Item2"></MenuItem>
                                    <MenuItem Header="Item3"></MenuItem>
                                </StackPanel>
                            </Grid>
                        </ScrollViewer>
                    </Border>
                </theme:SystemDropShadowChrome>
            </Popup>
            <Button.Triggers>
                <EventTrigger RoutedEvent="MouseRightButtonUp">
                    <BeginStoryboard>
                        <Storyboard>
                            <BooleanAnimationUsingKeyFrames Storyboard.TargetName="popup" Storyboard.TargetProperty="IsOpen">
                                <DiscreteBooleanKeyFrame KeyTime="00:00:00.1" Value="True"/>
                            </BooleanAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>
        </Button>
    </ScrollViewer>
    

    Remember to add a reference to PresentationFramework.Aero2.dll if you want to use SystemDropShadowChrome.