views:

1770

answers:

3

so I have attached a context menu (right-click menu) to a wpf listview.

unfortunately, when you right-click it brings up both the menu and selects whatever item you are over. Is there a way to shut off this right-click select behavior while still allowing the context menu?

+1  A: 

You must play with both the PreviewRightMouseDown and PreviewRightMouseUp events. Here is the XAML that achieves what you desire with the code behind given below:

<ListBox PreviewMouseRightButtonUp="ListBox_PreviewMouseRightButtonUp"
         PreviewMouseRightButtonDown="ListBox_PreviewMouseRightButtonDown">
    <ListBox.ContextMenu>
        <ContextMenu x:Name="contextMenu">
            <MenuItem Header="Test 1" />
            <MenuItem Header="Test 2" />
        </ContextMenu>
    </ListBox.ContextMenu>
    <ListBoxItem>Test 1</ListBoxItem>
</ListBox>

Code behind:

private void ListBox_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
    // a better version would turn the sender into the ListBoxItem
    // find the list box, then find the ContextMenu that way
    this.contextMenu.PlacementTarget = sender as UIElement;
    this.contextMenu.IsOpen = true;
}

private void ListBox_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    // disables the SelectedIndex code
    e.Handled = true;
}
sixlettervariables
I only have Kaxaml on my lappy, couldn't test for sure. Looking into playing with the input bindings.
sixlettervariables
It has no effect. However marking the (Preview)MouseRightButtonUp event as handled does stop the hightlighting and the context menu.
ChrisF
I don't think you'll need the PreviewMouseRightButtonUp event at all, though if you want information about the item you're over, you'll need it.
Ryan Versaw
+3  A: 

The key is setting the PreviewMouseRightButtonDown event in the correct place. As you'll notice, even without a ContextMenu right clicking on a ListViewItem will select that item, and so we need to set the event on each item, not on the ListView.

<ListView>
 <ListView.ItemContainerStyle>
  <Style TargetType="{x:Type ListViewItem}">
   <EventSetter Event="PreviewMouseRightButtonDown"
       Handler="OnListViewItemPreviewMouseRightButtonDown" />
  </Style>
 </ListView.ItemContainerStyle>
 <ListView.ContextMenu>
  <ContextMenu>
   <MenuItem Header="Menu Item">Item 1</MenuItem>
   <MenuItem Header="Menu Item">Item 2</MenuItem>
  </ContextMenu>
 </ListView.ContextMenu>
 <ListViewItem>Item</ListViewItem>
 <ListViewItem>Item</ListViewItem>
 <ListViewItem>Item</ListViewItem>
 <ListViewItem>Item</ListViewItem>
 <ListViewItem>Item</ListViewItem>
 <ListViewItem>Item</ListViewItem>
</ListView>


private void OnListViewItemPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
 Trace.WriteLine("Preview MouseRightButtonDown");

 e.Handled = true;
}

Since the preview events are tunneling this will block the RightMouseButtonDown from occurring on the ListViewItems preventing them from being selected, but not prevent the RightMouseButtonDown on the ListView and so still allow the ContextMenu to open.

rmoore
yes this is exactly what I needed. It works perfectly. Thanks!
KevinDeus