65.9K
CodeProject is changing. Read more.
Home

WPF: The Jumpy GridSplitter Fix

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2 votes)

Mar 7, 2016

CPOL

1 min read

viewsIcon

10725

When GridSplitter stops resizing by mouse, yet operates by keyboard arrows

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) // or e.HorizontalChange
    {
        // Splitter has stopped resizing grid rows:
        // BugFix: use keyboard for continuing resizing until user releases mouse
        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.