MENU

blog
スタッフブログ

dot
[WPF]入力制限拡張プロパティを追加したTextBox
技術

[WPF]入力制限拡張プロパティを追加したTextBox

こんにちは!
ソリューションセクションの日野です。

今回もWPFの拡張コントロールを作成したので紹介したいと思います

TextBoxを拡張して「Pattern」のプロパティを追加しました!
Patternに正規表現で指定することで文字入力時に指定の正規表現ではじいてくれます
動作はこんな感じです

ソースコード

実際のソースコードはこちら

PatternTextBox.cs

using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace WpfApp1
{
    class PatternTextBox : TextBox
    {
        /// <summary>
        /// 正規表現を指定するプロパティ
        /// </summary>
        public static readonly DependencyProperty PatternProperty =
            DependencyProperty.Register("Pattern", typeof(string), typeof(PatternTextBox), new PropertyMetadata(OnInitalizeData));

        /// <summary>
        /// 正規表現を保持
        /// </summary>
        private Regex reg;

        /// <summary>
        /// パターン
        /// </summary>
        public string Pattern
        {
            get
            {
                return (string)GetValue(PatternProperty);
            }
            set
            {
                SetValue(PatternProperty, value);
            }
        }

        /// <summary>
        /// テキスト入力時にパターンにマッチするか確認
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPreviewTextInput(TextCompositionEventArgs e)
        {
            //変更不可の場合は何もしない
            if (this.IsReadOnly)
            {
                return;
            }

            if (reg == null) return;
            if ((e.Text != "\r" && e.Text != "\t") && !reg.IsMatch(e.Text))
            {
                e.Handled = true;
                //正規表現でエラーになったときの処理
                //今回はTextを消してます
                Text = null;
            }
        }

        /// <summary>
        /// 初期化時にRegに反映
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="e"></param>
        protected static void OnInitalizeData(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var ctl = obj as PatternTextBox;
            if (ctl == null) return;
            if (ctl.Pattern != null)
            {
                ctl.reg = new Regex(ctl.Pattern);
            }
        }
    }
}

後はMainWindowのXamlで呼び出すときにPatternっていうプロパティを追加するだけです

MainWindow.xaml.cs

<Window x:Class="WpfApp1.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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="250">
    <Grid>
        <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
            <Label Content="数字のみOKなTextBox"/>
            <local:PatternTextBox Pattern="^[0-9]*$" Width="150"/>
            <Label Content="大文字英語だけOKなTextBox"/>
            <local:PatternTextBox Pattern="^[A-Z]*$" Width="150"/>
        </StackPanel>
    </Grid>
</Window>

最後に

ユーザビリティ的にも入力したときに入力がはじかれたりエラーが出たほうがわかりやすいですよね
WPFだと基本的にはPrivewTextInputなどのイベント指定してコードを書いて入力制限する方法が結構一般的かなと思うのですが、

画面内に大量にTextBoxがある・・・

いろんな画面で使うので似たようなソースコードがいっぱい・・・

とかそういったことが起きます
私はMainWindowのイベントに追加してすごいことになりました(´・ω・`)

なので拡張プロパティで設定できるとだいぶソースコードがすっきりするのではないでしょうか
それでは!

dot
dot
PAGETOP