Replacing the decimal point key (from numpad) with correct decimal separator (in silverlight!)
Asked Answered
C

8

0

What I am trying to do when the user is in a textbox (in silverlight 2.0):

  • When user presses the decimal point (.) on the numeric pad, I want to have it replaced by the correct decimal separator (which is comma (,) in a lot of countries)

I can track that the user typed a decimal point by checking in the keydown event

void Cell_KeyDown(object sender, KeyEventArgs e)
{
     if (e.Key == Key.Decimal)

But how do I replace that key with an other in Silverlight. The e.Key is read only. Is there a way to 'send an other key' to the control? Or any other suggestions?

Cambell answered 4/12, 2008 at 9:6 Comment(0)
C
0

Using Alterlife's answer as a hint for replacing contents, I have the following working hack... But I don't like it :-(.

  • It means that the Text property is set twice, once to the wrong value and then replaced by the right value
  • It only works for text boxes
  • It feels like a hack that someday might just stop working

So suggestions for better, more generic, solutions are very welcome!

The hack:

    void CellText_KeyUp(object sender, KeyEventArgs e)
    {
        var DecSep = System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator;

        if (e.Key == Key.Decimal && DecSep != ".")
        {
            if (e.OriginalSource is TextBox)
            {
                var TB = (TextBox)e.OriginalSource;
                string sText = TB.Text;

                int iPos = TB.SelectionStart - 1;
                if (iPos >= 0)
                {
                    System.Diagnostics.Debug.Assert(sText.Substring(iPos, 1) == ".");

                    TB.Text = sText.Substring(0, iPos) + DecSep + sText.Substring(iPos + 1);
                    TB.SelectionStart = iPos + 1; // reposition cursor
                }
            }
        }
    }
Cambell answered 4/12, 2008 at 10:32 Comment(0)
M
2

The answer was found on the website of MSDN: Replace-numpad-decimalpoint

Imports System.Threading
Imports System.Windows.Forms

Namespace My


    ' The following events are available for MyApplication:
    ' 
    ' Startup: Raised when the application starts, before the startup form is created.
    ' Shutdown: Raised after all application forms are closed.  This event is not raised if the application terminates abnormally.
    ' UnhandledException: Raised if the application encounters an unhandled exception.
    ' StartupNextInstance: Raised when launching a single-instance application and the application is already active. 
    ' NetworkAvailabilityChanged: Raised when the network connection is connected or disconnected.

    Partial Friend Class MyApplication
        Private Sub MyApplication_Startup(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) Handles Me.Startup
            If Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator <> "." Then
                System.Windows.Forms.Application.AddMessageFilter(New CommaMessageFilter)

            End If
        End Sub

    End Class

    Friend Class CommaMessageFilter
        Implements IMessageFilter
        Private Const WM_KEYDOWN = &H100

        Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements IMessageFilter.PreFilterMessage

            If m.Msg = WM_KEYDOWN Then
                Dim toets As Keys = CType(CType(m.WParam.ToInt32 And Keys.KeyCode, Integer), Keys)
                If toets = Keys.Decimal Then
                    SendKeys.Send(Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator)
                    Return True
                End If
            End If
            Return False
        End Function
    End Class

End Namespace
Masque answered 23/4, 2012 at 11:40 Comment(0)
B
1
public class NumericUpDown : System.Windows.Controls.NumericUpDown
{
    [DebuggerStepThrough]
    protected override double ParseValue(string text)
    {
        text = text.Replace(".", Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator);
        return base.ParseValue(text);
    }
}

Cheers

Bufflehead answered 31/8, 2011 at 13:44 Comment(0)
T
1

I have a solution for this that i use in my winforms apps, is suppose it should also work in silverlight. It's in vb, but converting it to c# shouldn't be a problem. Have a look here: http://code.msdn.microsoft.com/Replace-numpad-decimalpoint-c1e0e6cd

Tool answered 20/4, 2012 at 7:38 Comment(0)
B
0

You could do your changes in _LostFocus wether it's changing the dot to a comma, or applying the correct culture to the input.

It wouldn't do the change straight away as you desire, but would do it as soon as the user left the text box.

Bacterin answered 4/12, 2008 at 9:24 Comment(1)
Thanks for the suggestion, but from a users pov is that not very clear: he sees 1.5 until he leaves the tb and than it becomes 1,5...Cambell
J
0

You could probably read the 'key up' event instead of 'key down' and replace the entire content of the text box with your (entire) preferred substituted string on every keypress.

However, I think you're going about this the wrong way. There's a ',' key on the keyboard. I would assume that if your user meant to type in a ',' because that's the standard in his country, then that's what he would hit. Key substitution on screen would just be confusing.

Judie answered 4/12, 2008 at 9:41 Comment(1)
Thanks for your first suggestion... I will see what I can do there. But this is not confusing for users, for fast number typing they expect the numeric pad '.' to be the local decimal separator. That is also what excel does for example! So to be clear I am only talking about the . on the numpadCambell
C
0

Using Alterlife's answer as a hint for replacing contents, I have the following working hack... But I don't like it :-(.

  • It means that the Text property is set twice, once to the wrong value and then replaced by the right value
  • It only works for text boxes
  • It feels like a hack that someday might just stop working

So suggestions for better, more generic, solutions are very welcome!

The hack:

    void CellText_KeyUp(object sender, KeyEventArgs e)
    {
        var DecSep = System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator;

        if (e.Key == Key.Decimal && DecSep != ".")
        {
            if (e.OriginalSource is TextBox)
            {
                var TB = (TextBox)e.OriginalSource;
                string sText = TB.Text;

                int iPos = TB.SelectionStart - 1;
                if (iPos >= 0)
                {
                    System.Diagnostics.Debug.Assert(sText.Substring(iPos, 1) == ".");

                    TB.Text = sText.Substring(0, iPos) + DecSep + sText.Substring(iPos + 1);
                    TB.SelectionStart = iPos + 1; // reposition cursor
                }
            }
        }
    }
Cambell answered 4/12, 2008 at 10:32 Comment(0)
S
0

You're trying to override your system's locale settings, which may confuse your users when they are getting a wrong response from the key they typed in... What you can do is write a value converter, which would ensure the value will be properly formed before written to the bound data field. Assuming your textbox is bound to the underlying data field...

Strip answered 7/12, 2008 at 9:14 Comment(1)
Thanks for your answer, but no I am not trying to override the system's locale setting (at least I think not). I am trying to let the decimal point on the numpad being used as the DecimalSeparator. Which is what most (data entry) users expect.Cambell
T
0

It's working:

<html>
<heaD>
<script language="javascript">
function keypress1 ()
{
 var e=window.event || e
 unicode = e.charCode ? e.charCode : e.keyCode; 
 if (unicode==46)
   { return (e.charCode ? e.charCode=44 : e.keyCode=44); }
}
function keypress2 ()
{
 var e=window.event || e
 unicode = e.charCode ? e.charCode : e.keyCode; 
 if (unicode==46)
   { return (e.charCode ? e.charCode=46 : e.keyCode=46); }
}
function keyDown(e){
 if (!e){
   e = event
 }
 var code=e.keyCode;
 if(code==110)
   return document.onkeypress=keypress1
 else if(code=188)
   {  document.onkeypress=keypress2 }
}
document.onkeydown = keyDown
</script>
</head>
<body>
<input type=text>
</body>
</html>
Tl answered 13/11, 2009 at 4:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.