Introduction
Apart from Microsoft, it is common knowledge that the WPF GridSplitter
has problems with mouse operation in complex layouts. Then it may succeed, if user drags it deliberately slow, but suddenly jumps back to old position on normal mouse movement. However using keyboard arrows always works trouble-free.
AFAIG (as far as I can Google), there is no real known fix, apart from using custom splitters. Until proven otherwise, I deem the following code as a universal fix for the described problem.
Code
using System;
using System.Reflection;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
private readonly MethodInfo miMoveSplitter = typeof(GridSplitter)
.GetMethod("KeyboardMoveSplitter",BindingFlags.Instance | BindingFlags.NonPublic);
void GridSplitter_DragDelta(object sender, DragDeltaEventArgs e)
{
if (Math.Abs(e.VerticalChange) > 10) {
miMoveSplitter.Invoke(sender, new object[]{e.HorizontalChange, e.VerticalChange});
}
}
I assumed here a horizontal splitter resizing rows, for a vertical one test for DragDeltaEventArgs.HorizontalChange
.
10 proved a good threshold value for standard DragIncrement
of 1
.
Explanation
In normal dragging operation, the reported change by the DragDelta
event is roughly the DragIncrement
value. If the threshold is exceeded, GridSplitter
has stopped resizing (Grid
raises no more Layout
events), and cursor and splitter position will differ substantially. While the mouse is still captured, GridSplitter
won't recover, until the user releases the mouse. Now, we invoke a private
method used for processing keyboard input and the resizing will continue.
Points of Interest
If GridSplitter
works correctly, the cursor is centered on the dragged splitter; if the fix kicks in, you can notice a slight offset.