TextBox.KeyDown : remplacer un caractère
Hello,
Je suis en train de créer une DecimalTextBox qui, comme son nom l'indique, servira à faire encoder des nombres décimaux par les utilisateurs (car le DecimalUpDown de Xceed laisse vraiment à désirer...).
Bref, tout va très bien sauf que, plutôt que de me contenter de faire une validation avec ValidationRule de ce qui a été encoder, je voudrais aussi limité la saisie clavier. Ils pourront toujours encoder des conneries en faisant des copier-coller mais la ValidationRule est là pour leur dire qu'ils font de la merde.
Du coup, pour limiter la saisie clavier, j'ai fait ceci (vous pouvez voir que j'ai testé plusieurs choses déjà) :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| Private _test As Boolean = True
Private Sub tb_KeyDown(sender As Object, e As KeyEventArgs)
Dim newKey = e.Key
If _allowedNumKeys.Contains(e.Key) AndAlso Keyboard.IsKeyToggled(Key.NumLock) Then
'ok
ElseIf _allowedShiftedKeys.Contains(e.Key) AndAlso (Keyboard.IsKeyDown(Key.LeftShift) OrElse Keyboard.IsKeyDown(Key.RightShift) OrElse Keyboard.IsKeyToggled(Key.CapsLock)) Then
'ok
ElseIf (e.Key = Key.OemMinus OrElse e.Key = Key.Subtract) AndAlso MinValue < 0 Then
'ok
ElseIf (e.Key = Key.OemComma OrElse e.Key = Key.OemPeriod OrElse e.Key = Key.Decimal) AndAlso Not _test Then
'ok
ElseIf (e.Key = Key.OemComma OrElse e.Key = Key.OemPeriod OrElse e.Key = Key.Decimal) AndAlso _test Then
_test = False
Dim c = Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator.ToCharArray()(0)
e.Handled = True
'If tb.Text Is Nothing Then
' tb.Text = ""
'End If
'Dim pos = tb.SelectionStart
'If pos = tb.Text.Length Then
' tb.Text &= c.ToString
'Else
' tb.Text = tb.Text.Insert(pos, c)
'End If
'newKey = Key.Decimal
'tb.Select(pos + 1, 0)
Dim key As Key
If c = "," Then
key = Key.OemComma
ElseIf c = "." Then
key = Key.OemPeriod
End If
Dim args = New KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, key)
args.RoutedEvent = Keyboard.KeyDownEvent
InputManager.Current.ProcessInput(args)
_test = True
Else
e.Handled = True
End If
End Sub |
Ca marche très bien pour interdire la saisie de caractère comme les lettres par exemple. Par contre, pas moyen de faire un remplacement de caractère pour avoir le bon séparateur décimal en fonction de la culture de l'utilisateur. Histoire que s'il met un point alors qu'il faut une virgule, bin ça mette la virgule pour lui. (c'est surtout car la touche décimal du clavier ne donne pas le bon séparateur... un truc de fou)
Bref, auriez-vous une astuce pour parvenir à remplacer un caractère sur l'événement KeyDown d'un control de type TextBox en WPF svp ?
Merci d'avance.
EDIT : Si nécessaire, voici le code xaml du controle. Des fois que la méthode de validation aurait un impact...
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| <UserControl x:Class="Controls.NumericTextBox.DecimalTextBox" x:Name="DecimalTextBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:InnoFramework.Wpf"
xmlns:vr="clr-namespace:InnoFramework.Wpf.ValidationRules"
mc:Ignorable="d" >
<UserControl.Resources>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="BorderBrush" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid>
<TextBox x:Name="tb" KeyDown="tb_KeyDown">
<TextBox.Text>
<Binding Path="Value" UpdateSourceTrigger="PropertyChanged" ElementName="DecimalTextBox">
<Binding.ValidationRules>
<vr:StringToDecimalValidationRule ValidationStep="RawProposedValue"/>
<DataErrorValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
<Validation.ErrorTemplate>
<ControlTemplate>
<StackPanel>
<AdornedElementPlaceholder x:Name="textBox"/>
<TextBlock Text="{Binding CurrentItem.ErrorContent}" Foreground="Red" Background="LightYellow"/>
</StackPanel>
</ControlTemplate>
</Validation.ErrorTemplate>
</TextBox>
</Grid>
</UserControl> |