WPFで数字とハイフンとピリオドだけ入力できるテキストボックス、-0.0に意味はある?
入力できるのは0から9までの数字とハイフン"-"とピリオド"."
ハイフンが入力できる場所は先頭だけ
MainWindow.xaml
<Window x:Class="_20200618_数値入力用TextBox.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:_20200618_数値入力用TextBox" mc:Ignorable="d" Title="MainWindow" Height="150" Width="400" Name="MyWindow"> <Grid> <Viewbox Margin="10"> <StackPanel Width="200"> <TextBox x:Name="MyTextBox" TextAlignment="Center" Margin="5" InputMethod.IsInputMethodSuspended="True" PreviewKeyDown="MyTextBox_PreviewKeyDown" PreviewTextInput="MyTextBox_PreviewTextInput" LostFocus="MyTextBox_LostFocus" CommandManager.PreviewExecuted="MyTextBox_PreviewExecuted"/> <TextBox TextAlignment="Center" Margin="5"/> </StackPanel> </Viewbox> </Grid> </Window>
MainWindow.xaml.cs
using System.Windows; using System.Windows.Controls; using System.Windows.Input; // Visual Studio / WPF > link > TextBoxに数値しか入力できなくする > PreviewTextInput使用 | e.Handled = true; - Qiita //https://qiita.com/7of9/items/04793406f94d229a6c4d // C# WPF 数値のみ入力できるTextBoxを作る - 備忘録 //https://kagasu.hatenablog.com/entry/2017/02/14/155824 // TextBoxに数値のみを入力する[C# WPF] //https://vdlz.xyz/Csharp/WPF/Control/EditableControl/TextBox/TextBoxNumberOnly.html // [Tips][TextBox] キャレットの位置を取得する | HIROs.NET Blog //https://blog.hiros-dot.net/?p=1594 // テキストボックスのIME制御 - WPF覚え書き //https://sites.google.com/site/wpfjueeshuki/tekisutobokkusunoime-zhi-yu // 正規表現を使って文字列を置換するには?[C#/VB]:.NET TIPS - @IT //https://www.atmarkit.co.jp/ait/articles/1702/08/news023.html namespace _20200618_数値入力用TextBox { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void MyTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e) { var textbox = (TextBox)sender; string str = textbox.Text;//文字列 var inputStr = e.Text;//入力された文字 //正規表現で入力文字の判定、数字とピリオド、ハイフンならtrue bool neko = new System.Text.RegularExpressions.Regex("[0-9.-]").IsMatch(inputStr); //入力文字が数値とピリオド、ハイフン以外だったら無効 if (neko == false) { e.Handled = true;//無効 return;//終了 } //キャレット(カーソル)位置が先頭(0)じゃないときの、ハイフン入力は無効 if (textbox.CaretIndex != 0 && inputStr == "-") { e.Handled = true; return; } //2つ目のハイフン入力は無効(全選択時なら許可) if (textbox.SelectedText != str) { if (str.Contains("-") && inputStr == "-") { e.Handled = true; return; } } //2つ目のピリオド入力は無効 if (str.Contains(".") && inputStr == ".") { e.Handled = true; return; } } private void MyTextBox_LostFocus(object sender, RoutedEventArgs e) { //ピリオドの削除 //先頭か末尾にあった場合は削除 var tb = (TextBox)sender; string text = tb.Text; if (text.StartsWith('.') || text.EndsWith('.')) { text = text.Replace(".", ""); } // -. も変なのでピリオドだけ削除 text = text.Replace("-.", "-"); //数値がないのにハイフンやピリオドがあった場合は削除 if (text == "-" || text == ".") text = ""; tb.Text = text; } private void MyTextBox_PreviewExecuted(object sender, ExecutedRoutedEventArgs e) { //貼り付け無効 if (e.Command == ApplicationCommands.Paste) { e.Handled = true; } } //スペースキーが押されたときは、それを無効にする private void MyTextBox_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Space) e.Handled = true; } } }
<TextBox x:Name="MyTextBox" TextAlignment="Center" Margin="5" InputMethod.IsInputMethodSuspended="True" PreviewKeyDown="MyTextBox_PreviewKeyDown" PreviewTextInput="MyTextBox_PreviewTextInput" LostFocus="MyTextBox_LostFocus" CommandManager.PreviewExecuted="MyTextBox_PreviewExecuted"/>
IMEを休止状態にする
InputMethod.IsInputMethodSuspended="True"
Trueを指定したテキストボックスではIMEの状態に関わらず、半角英数字だけの入力になる
スペースキーが押されたときは無効にする
PreviewKeyDown="MyTextBox_PreviewKeyDown"
PreviewKeyDownイベント時に阻止
本当はこのあとのPreviewTextInputイベントで、入力された文字で検出したかったけど、スペースだけは方法がわからなかったのでキー入力で対処した
キー入力のPreviewTextInputイベントのときに入力文字の制限
PreviewTextInput="MyTextBox_PreviewTextInput"
入力文字の制限とハイフンの入力位置、2つ目のハイフンとピリオドの制限をしている
制限に引っかかったらイベントのHandledにtrueを指定してイベントをスルー
ここまでだと
.123
123.
-.123
-
.
とかの不自然なのも入力できてしまうので、これは
フォーカスを失ったときのLostFocusイベントで対処
LostFocus="MyTextBox_LostFocus"
StringのReplaceメソッドで地道に削除している
貼り付け無効
CommandManager.PreviewExecutedイベント時に対処
CommandManager.PreviewExecuted="MyTextBox_PreviewExecuted"
これで完成
0の表示
0埋め
000987
これはいい
小数点以下の連続0
3.000
これも正確さを表すから、これもわかる
負数を0埋め
-00987
多少不自然な気もするけど、気のせいだと思う
負の0
-0
-00.00
これらも入力できるんだけど意味あるのかなあってググったら
ja.wikipedia.org
難しいこと書いてあるけど、場合によっては意味があるみたい
じゃあC#の場合はどうなのか
0.0と-0.0
==やEqualsでの判定だとtrueになるけど
1.0 / 0.0 = infinity
1.0 / -0.0 = -infinity
割り算だと違う結果になった
それよりも0.0での割り算でエラーにならないのに驚いたわ、0だと赤波線でのエラー表示になる
-0.0をdouble.Parseで数値に変換すると0になるけど、内部的には-0.0のままみたい(36と44行目)
ってことで意味はあるけど、普通に使う分には変わんないかな
参照したところ
Visual Studio / WPF > link > TextBoxに数値しか入力できなくする > PreviewTextInput使用 | e.Handled = true; - Qiita
C# WPF 数値のみ入力できるTextBoxを作る - 備忘録
kagasu.hatenablog.com
TextBoxに数値のみを入力する[C# WPF]
vdlz.xyz
[Tips][TextBox] キャレットの位置を取得する | HIROs.NET Blog
blog.hiros-dot.net
テキストボックスのIME制御 - WPF覚え書き
sites.google.com
正規表現を使って文字列を置換するには?[C#/VB]:.NET TIPS - @IT
www.atmarkit.co.jp
関連記事
次のWPF記事は翌日
前回のWPF記事は20日前
gogowaten.hatenablog.com
今回のを利用したのが明後日
gogowaten.hatenablog.com