locked
Modal Window "Enter" key bug fix? RRS feed

  • Question

  • Hi,

    I went through a few discussions on the forum about fixing the "Enter" key bug in a modal window but I could not find any solution to it so far. I have a datagrid and a few search fields (text boxes) in my modal window. When I fill a value in one field and move to another field, the grid populates based on that search criteria. But if I enter a value and hit the Enter key, the window closes. Has anybody worked around this? Yann's code was pretty interesting (link below) and I hoped this custom modal window would kill the bug. But it did not. Improved Modal Window Helper Class (based on Sheel's Article "Creating a Custom Add Or Edit Dialog")

    It would be great if someone could help.

    Thanks


    Chin
    Monday, December 5, 2011 10:02 PM

Answers

  • Hi Chin,

    This workaround may be what you're looking for. Although not the cleanest possible solution, it is rather straightforward to implement. Instead of stopping the enter key event at the dialog level, it can be stopped at the control level:

    void Table1ItemsListDetail_Created()

    {

    this.FindControl("TextBoxInModalWindowName").ControlAvailable += new EventHandler<ControlAvailableEventArgs>(Table1ItemsListDetail_ControlAvailable);

    }

    void Table1ItemsListDetail_ControlAvailable(object sender, ControlAvailableEventArgs e)

    {

    TextBox t = (TextBox)e.Control;

    t.KeyUp +=

    new System.Windows.Input.KeyEventHandler(t_KeyUp);

    }

    void t_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)

    {

    if (e.Key == System.Windows.Input.Key.Enter)

    {

    e.Handled =

    true;

    }

    }

    I tested this on a textbox field for a parameterized query in a modal window and I got the desired behavior on enter (value committed and data grid updated, but modal window not closed).

    Regards,

    Burt

    • Proposed as answer by Sébastien Barré Thursday, December 15, 2011 11:20 AM
    • Marked as answer by ChinmayWatve Thursday, December 15, 2011 7:50 PM
    Tuesday, December 13, 2011 7:21 PM

All replies

  • Hi Chin,

    This workaround may be what you're looking for. Although not the cleanest possible solution, it is rather straightforward to implement. Instead of stopping the enter key event at the dialog level, it can be stopped at the control level:

    void Table1ItemsListDetail_Created()

    {

    this.FindControl("TextBoxInModalWindowName").ControlAvailable += new EventHandler<ControlAvailableEventArgs>(Table1ItemsListDetail_ControlAvailable);

    }

    void Table1ItemsListDetail_ControlAvailable(object sender, ControlAvailableEventArgs e)

    {

    TextBox t = (TextBox)e.Control;

    t.KeyUp +=

    new System.Windows.Input.KeyEventHandler(t_KeyUp);

    }

    void t_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)

    {

    if (e.Key == System.Windows.Input.Key.Enter)

    {

    e.Handled =

    true;

    }

    }

    I tested this on a textbox field for a parameterized query in a modal window and I got the desired behavior on enter (value committed and data grid updated, but modal window not closed).

    Regards,

    Burt

    • Proposed as answer by Sébastien Barré Thursday, December 15, 2011 11:20 AM
    • Marked as answer by ChinmayWatve Thursday, December 15, 2011 7:50 PM
    Tuesday, December 13, 2011 7:21 PM
  • Thanks a lot for this neat solution Burt.
    Chin
    Thursday, December 15, 2011 7:53 PM
  • Hi,

    has anyone a visual basic version of the code?

    Thanks.

    Wednesday, December 21, 2011 10:49 AM
  • Try this:

    Private Sub Table1ItemsListDetail_Created() Me.FindControl("TextBoxInModalWindowName").ControlAvailable += New EventHandler(Of ControlAvailableEventArgs)(AddressOf Table1ItemsListDetail_ControlAvailable) End Sub Private Sub Table1ItemsListDetail_ControlAvailable(sender As Object, e As ControlAvailableEventArgs) Dim t As TextBox = DirectCast(e.Control, TextBox) t.KeyUp += New System.Windows.Input.KeyEventHandler(AddressOf t_KeyUp) End Sub Private Sub t_KeyUp(sender As Object, e As System.Windows.Input.KeyEventArgs) If e.Key = System.Windows.Input.Key.Enter Then e.Handled = True End If End Sub

    Chin
    Wednesday, December 21, 2011 1:58 PM
  • Hi,

    this code works for vb:

    Private Sub Table1ItemsListDetail_Created()
    AddHandler Me.FindControl("TextBoxInModalWindowName").ControlAvailable, AddressOf Table1ItemsListDetail_ControlAvailable
    End Sub
    
    Private Sub Table1ItemsListDetail_ControlAvailable(sender As Object, e As ControlAvailableEventArgs)
    	AddHandler CType(e.Control, System.Windows.Controls.TextBox).KeyUp, AddressOf t_KeyUp
    End Sub
    
    Private Sub t_KeyUp(sender As Object, e As System.Windows.Input.KeyEventArgs)
    	If e.Key = System.Windows.Input.Key.Enter Then
    		e.Handled = True
    	End If
    
    End Sub
    

    Markus

    Tuesday, December 27, 2011 3:42 PM
  • Hi,

    is it possible to fire for example the ok_button code of the modal window in the t_KeyUp function?

    If I try to do it with Me.OK_Button(), I will get an InvalidOperationException Error.

    Thanks.

    Markus

    Tuesday, December 27, 2011 4:18 PM
  • Hi,

    I think I have found a solution.

    Here the t_KeyUp function:

    Public Sub TextBoxKeyup(sender As Object, e As System.Windows.Input.KeyEventArgs)
                If e.Key = System.Windows.Input.Key.Enter Then
                    Me.Details.Dispatcher.BeginInvoke(Sub()
                                                              Me.OK_Button()
                                                      End Sub)
                End If
            End Sub
    

    But first I had a problem, because every time when I hit the enter button in the textbox I added an eventhandler.

    Because of this I decided to remove the first eventhandler in the Table1ItemsListDetail_ControlAvailable function.

    Private Sub Table1ItemsListDetail_ControlAvailable(sender As Object, e As ControlAvailableEventArgs)
    	AddHandler CType(e.Control, System.Windows.Controls.TextBox).KeyUp, AddressOf t_KeyUp
            RemoveHandler Me.FindControl("TextBoxInModalWindowName").ControlAvailable, AddressOf Table1ItemsListDetail_ControlAvailable
    End Sub
    

     

    Markus

    Wednesday, December 28, 2011 9:28 AM
  • Thanks Markus.. your question and solution helps!
    Chin
    Wednesday, December 28, 2011 4:02 PM
  • Hello Markus!

    i have already removed "X" buttons from modal windows, but i cant seem to get this piece of code to work,

    i.m. i still cant get ENTER problem solved...    are You sure that code should be exactly like this?

    Thanks for your time, this would mean a lot, as modal window "enter" seems to confuse some of the users...

    Tuesday, April 24, 2012 7:44 AM
  • It seems the issue with the Enter key closing modal windows is still here.

    I went throught this issue the first day last week when I added a modal window to my LS application and reading a lot of threads, I can't figure out how to avoid Enter closing my dialog.

    I use LS2012 and in my dialog there are controls that need to use the enter key, for example to trigger the _Changed event but in this situation in addition to trigger the event it closes the dialog.

    It's increadible that there isn't a default way to avoid this with a property in the modal window definition, this should be in my humble opinion the correct way to avoid this behavior by design.

    Has anybody a real workaround to avoid the enter key closing the modal dialog?

    Antonio

    Sunday, February 3, 2013 3:48 PM
  • void Table1ItemsListDetail_Created()

    {

    this.FindControl("TextBoxInModalWindowName").ControlAvailable += newEventHandler<ControlAvailableEventArgs>(Table1ItemsListDetail_ControlAvailable);

    }

    void Table1ItemsListDetail_ControlAvailable(object sender, ControlAvailableEventArgs e)

    {

    TextBox t = (TextBox)e.Control;

    t.KeyUp +=

    new System.Windows.Input.KeyEventHandler(t_KeyUp);

    }

    void t_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)

    {

    if (e.Key == System.Windows.Input.Key.Enter)

    {

    e.Handled =

    true;

    }

    }

    Try this. It worked for me.


    Chin

    Monday, February 4, 2013 5:01 PM
  • Thanks Chin,

    I tried this solution and it seems working, the bad aspect of this is that if I have lots of controls on a modal window, I need to repeat the code for all controls I have to stop the Enter key closing the modal window.

    I tried to intercept the Enter key at the modal window level and handling the _Closing event to set the e.Cancel property to true... unfortunately the _Closing event fires befor the _KeyUp event and it is not working in my case.

    It is strange that the _Closing event fires before the _KeyUp...  I will give another check to see if I made something wrong.

    Monday, February 11, 2013 3:03 PM
  • The _Closing event definitively fires before the _KeyUp event, so handling the _KeyUp at the dialog level doesn't work... It seems there is no alternative than intercept the _KeyUp in all controls present on the dialog, unless somebody has any other idea... :)
    Monday, February 18, 2013 6:35 AM
  • Burt,

    Great solution.

    I'm just wondering if it's necessary to unsubscribe the events when the screen is closed?


    paul van bladel

    Tuesday, February 19, 2013 8:22 AM
  • I elaborated an extension method, which can make the above a bit more easy to setup:

    A PRACTICAL EXTENSION METHOD FOR THE MODAL WINDOW ENTER KEY “BUG” IN LIGHTSWITCH.


    paul van bladel

    Tuesday, February 19, 2013 1:54 PM
  • Great Paul,

    Thank you for the solution.

    Wednesday, February 20, 2013 2:16 AM
  • I tried a different solution, and it works as well, just handling the KeyUp event at the top RowsLayout without the need to go down to all child items as you did.

    The extension I created is the following (copied from your code :))

    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 SuppressEnterKeyForControl(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;
                                };
                        };
    
            }
        }
    }
    

    and I used it in my screen in the _Created event as you did, in my case the the modal window in the screen is named SelectArticleDialog and the top RowsLayout is named SelectArticleDialogLayout

            partial void CreateNewPurchaseOrder_Created()
            {
                // Write your code here.
                this.SuppressEnterKeyForControl("SelectArticleDialogLayout");
            }
    

    Wednesday, February 20, 2013 2:55 AM
  • That's a great improvement.

    You know why this works? 

    I changed the TextBox to UIElement

     (e1.Control as UIElement)
                            .KeyUp += (s2, e2) =>

    Before in this post,the event was attached to TextBox.

    Well.. due to the generic nature of UIElement (dropdown, textbox,... are all UIElement), the event bubbling mechanism (which is soo cool in Xaml) can play perfectly it's role, meaning that all underlying controls in the parent control in the modal window will look for a keyup event. (see: http://msdn.microsoft.com/en-us/library/cc189018(v=vs.95).aspx)


    paul van bladel

    Wednesday, February 20, 2013 6:50 AM
  • Hi, the code below solve the problem.

    Solutions bugs:

    1) The control where you press enter lost focus

    2) You must hide the close button in upper coner

    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 Microsoft.LightSwitch.Runtime.Shell.Framework;

    namespace LightSwitchApplication
    {
        public partial class EditableGrid
        {
            private bool _buttonPressed;

            partial void EditableGrid_InitializeDataWorkspace(List<IDataService> saveChangesTo)
            {
                this.FindControl("NewModalWindow").ControlAvailable +=
                    (sender, args) =>
                        {
                            var ctr = args.Control as ScreenChildWindow;
                            if (ctr == null) return;

                            ctr.HasCloseButton = false;
                            ctr.Closing +=
                                (o, eventArgs) =>
                                    {
                                        if (_buttonPressed)
                                            eventArgs.Cancel = _buttonPressed = false;
                                        else
                                            eventArgs.Cancel = true;
                                    };
                        };
            }

            partial void ConfirmMethod_Execute()
            {
                _buttonPressed = true;
                this.CloseModalWindow("NewModalWindow");
            }

            partial void CancelMethod_Execute()
            {
                _buttonPressed = true;
                this.CloseModalWindow("NewModalWindow");
            }

            partial void OpenModalWindowMethod_Execute()
            {
                this.OpenModalWindow("NewModalWindow");
            }
        }
    }

    Wednesday, February 27, 2013 9:57 PM