A practical extension method for the modal window enter key “bug” in LightSwitch.

Introduction

When you have in a LightSwitch screen, a modal window, there is the annoying behavior that pressing the enter key closes you modal window.

There is a workaround available on the user forum: http://social.msdn.microsoft.com/Forums/en-US/lightswitch/thread/174264d3-f094-46e5-b5a7-6a606916070d?prof=required.

The idea of this workaround is to hook up the “key up” event on every input control of the modal window.

It’s working great, but it can be a source of errors: controls can be renamed, fields can be added, etc. …

Note: See the important update at the end of this post !!

Let’s improve it

Let’s assume we have following modal window with 4 fields: 2 textboxes, a modal window picker and a autocomplete box.

modal

 

 

How do we trigger the fix?

partial void SearchCustomers_Created()
        {

            this.SuprresEnterKeyForUnderlyingControls("CurrentCustomer");

          }

As you can see, simply one line of code, an extension method on the ScreenObject. Note that we do not specify the name of the modal window, but the first underlying group control (in my case a rows layout).

Show me the extension class…

using System;
using System.Linq;
using System.IO;
using System.IO.IsolatedStorage;
using System.Collections.Generic;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Framework.Client;
using Microsoft.LightSwitch.Presentation;
using Microsoft.LightSwitch.Presentation.Extensions;
using System.Windows.Controls;
using Microsoft.LightSwitch.Model;
using Microsoft.LightSwitch.Client;
using System.Windows;
using System.Windows.Input;
namespace LightSwitchApplication
{

    public static class IScreenObjectExtensions
    {
        public static void SuprresEnterKeyForUnderlyingControls(this IScreenObject screen, string parentControlName)
        {
            IContentItemDefinition itemDef = screen.Details.GetModel().GetChildItems(true)
                .OfType<IContentItemDefinition>()
                .Where(c => c.Name == parentControlName).FirstOrDefault();
            foreach (var item in itemDef.ChildContentItems)
            {
                SuppressEnterKey(screen, item);
            }
        }

        private static void SuppressEnterKey(IScreenObject screen, IContentItemDefinition contentItemDefinition)
        {
            var proxy = screen.FindControl(contentItemDefinition.Name);
            proxy.ControlAvailable += (s1, e1) =>
                 {
                     UIElement uiElement = e1.Control as UIElement;
                     uiElement.KeyUp += (s2, e2) =>
                          {
                              if (e2.Key == Key.Enter || e2.Key==Key.Escape)
                                  e2.Handled = true;
                          };
                 };
        }
    }
}

Update

Someone on the LightSwitch forum correctly draw my attention to the fact that things can be more simplified. In fact via model inspection, I retrieve the list of controls present in the modal form. Since I attach the Key up event on a UIElement, the event bubbling mechanism can play it’s role here. So the model inspection is no longer necessary. So, this can simplify the extension method as follows:

public static void SuprresEnterKeyForUnderlyingControls(this IScreenObject screen, string controlName)
        {
            screen.FindControl(controlName)
                .ControlAvailable += (s1, e1) =>
                {
                    (e1.Control as UIElement)
                    .KeyUp += (s2, e2) =>
                    {
                        if (e2.Key == Key.Enter)
                            e2.Handled = true;
                    };
                };
        }

Conclusion

What can I say more? Again an example that LightSwitch is simple on the outside, but rich on the inside…