Tips and Tricks for C# Metro developers: Handling the virtual keyboard

As we saw in a previous post (https://blogs.msdn.com/b/eternalcoding/archive/2012/07/03/tips-and-tricks-for-c-metro-developers-the-flyout-control.aspx) it is really easy to create a flyout control.

But if this control is used to type text, you must consider handling the virtual keyboard in order to move your flyout so that it can always be visible:

To do so, it is pretty easy because WinRT has an event for that:

Windows.UI.ViewManagement.InputPane.GetForCurrentView().Showing 

So to always keep your flyout on top off its control, just use the following code:

// Handling the virtual keyboard
int flyoutOffset = 0;
Windows.UI.ViewManagement.InputPane.GetForCurrentView().Showing += (s, args) =>
    {
        flyoutOffset = (int)args.OccludedRect.Height;
        flyout.VerticalOffset -= flyoutOffset;
    };
Windows.UI.ViewManagement.InputPane.GetForCurrentView().Hiding += (s, args) =>
    {
        flyout.VerticalOffset += flyoutOffset;
    };

So the complete flyout code is as follows:

public static Popup ShowPopup(FrameworkElement source, UserControl control)
{
    Popup flyout = new Popup();

    var windowBounds = Window.Current.Bounds;
    var rootVisual = Window.Current.Content;

    GeneralTransform gt = source.TransformToVisual(rootVisual);

    var absolutePosition = gt.TransformPoint(new Point(0, 0));

    control.Measure(new Size(Double.PositiveInfinity, double.PositiveInfinity));

    flyout.VerticalOffset = windowBounds.Height - control.Height - 120;
    flyout.HorizontalOffset = (absolutePosition.X + source.ActualWidth / 2) - control.Width / 2;
    flyout.IsLightDismissEnabled = true;

    flyout.Child = control;
    var transitions = new TransitionCollection();
    transitions.Add(new PopupThemeTransition() { FromHorizontalOffset = 0, FromVerticalOffset = 100 });
    flyout.ChildTransitions = transitions;
    flyout.IsOpen = true;

    // Handling the virtual keyboard
    int flyoutOffset = 0;
    Windows.UI.ViewManagement.InputPane.GetForCurrentView().Showing += (s, args) =>
        {
            flyoutOffset = (int)args.OccludedRect.Height;
            flyout.VerticalOffset -= flyoutOffset;
        };
    Windows.UI.ViewManagement.InputPane.GetForCurrentView().Hiding += (s, args) =>
        {
            flyout.VerticalOffset += flyoutOffset;
        };

    return flyout;
}