Il faut modifier la classe ListBox pour explicitement signaler que les items de la listbox ne seront pas des ListBoxItem mais des "custom" items. Il faut modifier l'action click droit "down" .. C'est en effet lors de cet événement que la listbox modifie la sélection sur les items. Il faut gérer les cas ou on utilise en plus la touche "Ctrl" ou "Shift". Après quelques modifications, on obtient le même comportement que la listbox de l'explorateur Windows ;-)
[csharp]
public class WindowsListBox : System.Windows.Controls.ListBox
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new WindowsListBoxItem();
    }
}

public class WindowsListBoxItem : System.Windows.Controls.ListBoxItem
{
    protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
    {
        ListBox parentListBox = ParentListBox;
        if (parentListBox != null)
        {
            if (parentListBox.SelectionMode == SelectionMode.Extended)
            {
                if ((Keyboard.Modifiers & (ModifierKeys.Shift | ModifierKeys.Control)) 
                    != (ModifierKeys.Shift | ModifierKeys.Control))
                {
                    if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                    {
                        return;
                    }
                    else if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
                    {
                        if (!IsSelected)
                        {
                            parentListBox.SelectedItems.Clear();
                            IsSelected = true;
                        }
                    }
                    else
                    {
                        parentListBox.SelectedItems.Clear();
                        IsSelected = true;
                        Focus();
                    }
                }
                return;
            }
        }

        base.OnMouseRightButtonDown(e);
    }

    private ListBox ParentListBox
    {
        get
        {
            return ItemsControl.ItemsControlFromItemContainer(this) as ListBox;
        }
    }
}

L'utilisation de cette modification se fait simplement. On retrouve dans le code XAML la même structure que lors de l'utilisation d'une listbox standard.
[xml]
<Window x:Class="WpfTests.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ListBoxWPFMultiTest" Height="300" Width="300"
    xmlns:local="clr-namespace:WpfTests"
    >
    <Window.Resources>
      <ContextMenu x:Key="listBoxItemMenuItems">
        <MenuItem Header="Details..." Click="OnClick"/>
      </ContextMenu>
      <Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="ContextMenu" Value="{DynamicResource listBoxItemMenuItems}"/>
      </Style>
    </Window.Resources>
    <Grid>
      <local:WindowsListBox x:Name="m_listbox" SelectionMode="Extended"/>
    </Grid>
</Window>

[csharp]
public partial class Window1 : System.Windows.Window
{

    public Window1()
    {
        InitializeComponent();
        List col = new List();
        col.Add("Chaine 1");
        col.Add("Chaine 2");
        col.Add("Chaine 3");
        col.Add("Chaine 4");
        col.Add("Chaine 5");
        col.Add("Chaine 6");
        col.Add("Chaine 7");
        col.Add("Chaine 8");
        col.Add("Chaine 9");
        col.Add("Chaine 10");
        m_listbox.ItemsSource = col;
    }

    private void OnClick(object sender, RoutedEventArgs e)
    {
        StringBuilder builder = new StringBuilder();
        foreach(object item in m_listbox.SelectedItems)
        {
            ListBoxItem listBoxItem = (ListBoxItem)m_listbox.ItemContainerGenerator.ContainerFromItem(item);
            builder.AppendLine(string.Format("Item {0}, Focused {1}", item, listBoxItem.IsFocused));
        }
        MessageBox.Show(builder.ToString());
    }
}