Indeed the Winforms Control keeps the mouse event for himself and doesn't forward the event to its host. The solution is to subscribe to the winforms MouseDown event and generate programmatically the Routed Event.
I overrided the WindowsFormsHost as following and it rocks:
(remark: a behavior may be more flexible)
public class ExtendedWindowsFormsHost : WindowsFormsHost
{
public ExtendedWindowsFormsHost()
{
ChildChanged += OnChildChanged;
}
private void OnChildChanged(object sender, ChildChangedEventArgs childChangedEventArgs)
{
var previousChild = childChangedEventArgs.PreviousChild as Control;
if (previousChild != null)
{
previousChild.MouseDown -= OnMouseDown;
}
if (Child != null)
{
Child.MouseDown += OnMouseDown;
}
}
private void OnMouseDown(object sender, MouseEventArgs mouseEventArgs)
{
MouseButton? wpfButton = ConvertToWpf(mouseEventArgs.Button);
if (!wpfButton.HasValue)
return;
RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, wpfButton.Value)
{
RoutedEvent = Mouse.MouseDownEvent,
Source = this,
});
}
private MouseButton? ConvertToWpf(MouseButtons winformButton)
{
switch (winformButton)
{
case MouseButtons.Left:
return MouseButton.Left;
case MouseButtons.None:
return null;
case MouseButtons.Right:
return MouseButton.Right;
case MouseButtons.Middle:
return MouseButton.Middle;
case MouseButtons.XButton1:
return MouseButton.XButton1;
case MouseButtons.XButton2:
return MouseButton.XButton2;
default:
throw new ArgumentOutOfRangeException("winformButton");
}
}
}