WPFにもNumericUpDownみたいなのをユーザーコントロールで、その2
昨日の続き
入力制限は一昨日のをコピペして、あとはクリックしたときに文字列全部を選択するのを追加した
UserControl1.xaml
<UserControl x:Class="ControlLibraryCore20200620.UserControl1" 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:ControlLibraryCore20200620" mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="200"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition Width="16"/> </Grid.ColumnDefinitions> <RepeatButton Grid.Row="0" Grid.Column="1" IsTabStop="False"> <RepeatButton.Content> <Viewbox x:Name="ViewBoxUp" Margin="1"> <Polygon Points="1,0 2,1 0,1 1,0" Fill="Gray"/> </Viewbox> </RepeatButton.Content> </RepeatButton> <RepeatButton Grid.Row="1" Grid.Column="1" IsTabStop="False"> <RepeatButton.Content> <Viewbox x:Name="ViewBoxDown" Margin="1"> <Polygon Points="0,0 2,0 1,1 0,0" Fill="Gray"/> </Viewbox> </RepeatButton.Content> </RepeatButton> <TextBox x:Name="MyTextBox" Grid.RowSpan="2" Grid.Column="0" TextAlignment="Right" VerticalContentAlignment="Center" InputMethod.IsInputMethodSuspended="True" PreviewKeyDown="MyTextBox_PreviewKeyDown" PreviewTextInput="MyTextBox_PreviewTextInput" LostFocus="MyTextBox_LostFocus" CommandManager.PreviewExecuted="MyTextBox_PreviewExecuted" GotFocus="MyTextBox_GotFocus" PreviewMouseLeftButtonDown="MyTextBox_PreviewMouseLeftButtonDown"> </TextBox> </Grid> </UserControl>
UserControl1.xaml.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace ControlLibraryCore20200620 { /// <summary> /// Interaction logic for UserControl1.xaml /// </summary> public partial class UserControl1 : UserControl { public UserControl1() { InitializeComponent(); } //スペースキーが押されたのを無効にする private void MyTextBox_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Space) e.Handled = true; } //入力の制限、数字とハイフンとピリオドだけ通す 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; } } //focusしたときにテキストを全選択 private void MyTextBox_GotFocus(object sender, RoutedEventArgs e) { var tb = sender as TextBox; tb.SelectAll(); } // | オールトの雲 //http://ooltcloud.sakura.ne.jp/blog/201311/article_30013700.html //クリックしたときにテキストを全選択 private void MyTextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { var tb = sender as TextBox; if (tb.IsFocused == false) { tb.Focus(); e.Handled = true; } } } }
XAMLの
RepeatButton部分
Tabキーで遷移するときにRepeatButtonは無視するようにしたのが、19と26行目のIsTabStop="False"
TextBox部分
36~40は一昨日のコピペ
41行目GotFocusはフォーカスを得たときに、テキスト全選択
42行目PreviewMouseLeftButtonDownは左クリック時にもテキスト全選択
この部分の処理は
フォーカスを得たときにテキストを全選択は、TextBoxのSelectAllメソッドを実行するだけ
これでいいはずなんだけど、クリックで選択(フォーカス)されたときは、一瞬だけ全選択されるんだけど直後に解除されてしまう。どうやらそういう仕様みたいで、これを解決したのが
| オールトの雲
ooltcloud.sakura.ne.jp
こちらで紹介されていた方法
PreviewMouseLeftButtonDown時にフォーカスして(111行目)、それ以降の動作をキャンセルする(112行目)
ここまで書いたらビルドしてDLLファイルを更新
ビルドしないと動作確認用のプロジェクトで参照しているDLLファイルは、古い状態のままなので変更が反映されない
動作確認用アプリのデザイン画面
Tabキーでの遷移の状態を見るために2つ並べた
関連記事
次回は明日
gogowaten.hatenablog.com
前回は昨日
gogowaten.hatenablog.com
コピペ元は一昨日
gogowaten.hatenablog.com