8

The tricky part is that each item has a ContextMenu that I still want to open when it is right-clicked (I just don't want it selecting it).

In fact, if it makes things any easier, I don't want any automatic selection at all, so if there's some way I can disable it entirely that would be just fine.

I'm thinking of just switching to an ItemsControl actually, so long as I can get virtualization and scrolling to work with it.

devios1
  • 33,997
  • 43
  • 149
  • 241

1 Answers1

23

If you don't want selection at all I would definitely go with ItemsControl not ListBox. Virtualization and scrolling both can be used with a plain ItemsControl as long as they are in the template.

On the other hand, if you need selection but just don't want the right click to select, the easiest way is probably to handle the PreviewRightMouseButtonDown event:

void ListBox_PreviewRightMouseButtonDown(object sender, MouseButtonEventArgs e)
{
  e.Handled = true;
}

The reason this works is that ListBoxItem selection happens on mouse down but context menu opening happens on mouse up. So eliminating the mouse down event during the preview phase solves your problem.

However this does not work if you want mouse down to be handled elsewhere within your ListBox (such as in a control within an item). In this case the easiest way is probably to subclass ListBoxItem to ignore it:

public class ListBoxItemNoRightClickSelect : ListBoxItem
{
  protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
  {
  }
}

You can either explicitly construct these ListBoxItems in your ItemsSource or you can also subclass ListBox to use your custom items automatically:

public class ListBoxNoRightClickSelect : ListBox
{
  protected override DependencyObject GetContainerForItemOverride()
  {
    return new ListBoxItemNoRightClickSelect();
  }
}

FYI, here are some solutions that won't work along with explanations why they won't work:

  • You can't just add a MouseRightButtonDown handler on each ListBoxItem because the registered class handler will get called before yours
  • You can't handle MouseRightButtonDown on ListBox because the event is directly routed to each control individually
Ray Burns
  • 59,824
  • 12
  • 133
  • 138
  • Thanks--I ended up going the ItemsControl route, (implemented as here http://stackoverflow.com/questions/2783845/wpf-virtualizing-an-itemscontrol) and not only does it now work as I'd like, performance increased noticeably too! – devios1 Jun 10 '10 at 19:31