0

次のように、最小入力と最大入力も持つ TextBox に基づいてカスタム コントロールを作成しました。

    public class NumericTextBox : TextBox
    {
        static NumericTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericTextBox), new FrameworkPropertyMetadata(typeof(NumericTextBox)));
        }


        public static readonly DependencyProperty MinimumProperty =
            DependencyProperty.Register("Minimum", typeof(int), typeof(NumericTextBox), new PropertyMetadata(default(int)));

        public int Minimum
        {
            get { return (int)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }

        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(int), typeof(NumericTextBox), new PropertyMetadata(100));

        public int Maximum
        {
            get { return (int)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }


        public new static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(int), typeof(NumericTextBox),
                                        new FrameworkPropertyMetadata(
                                            default(int),
                                            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                            null,
                                            CoerceCurrentValue),
                                            IsValid);

        public new int Text
        {
            get { return (int)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }


        private static object CoerceCurrentValue(DependencyObject d, object baseValue)
        {
            var numericTextBox = (NumericTextBox)d;
            var intValue = (int)baseValue;
            if (intValue < numericTextBox.Minimum) intValue = numericTextBox.Minimum;
            if (intValue > numericTextBox.Maximum) intValue = numericTextBox.Maximum;

            if ((int)baseValue != intValue)
                numericTextBox.Text = intValue;

            return intValue;
        }

        private static bool IsValid(object value)
        {

            if (value == null)
                return false;

            int intValue;
            var result = Int32.TryParse(value.ToString(), out intValue);

            return result;


        }
}

そして私のxamlで私はそれを呼び出します:

<controls:NumericTextBox
    Grid.Row="0"
    Grid.Column="1"
    Margin="5"
    VerticalAlignment="Center"
    Text="{Binding Test, UpdateSourceTrigger=PropertyChanged}"
    Minimum="0"
    Maximum="100"
    />

これは、ビュー モデルの Test プロパティにバインドされます (int として)。文字を入力してバインディングエラーが発生するまで、すべてがうまく機能します。

System.Windows.Data エラー: 7: ConvertBack は値 '1a' (タイプ 'String') を変換できません。BindingExpression: パス = テキスト; DataItem='NumericTextBox' (Name=''); ターゲット要素は 'TextBox' (Name='') です。ターゲット プロパティは 'Text' (タイプ 'String') です FormatException:'System.FormatException: 入力文字列が正しい形式ではありませんでした。System.Number.StringToNumber (文字列 str、NumberStyles オプション、NumberBuffer& 数値、NumberFormatInfo 情報、ブール値 parseDecimal) で System.Number.ParseInt32 (文字列 s、NumberStyles スタイル、NumberFormatInfo 情報) で System.String.System.IConvertible.ToInt32 (IFormatProviderプロバイダー)
System.Convert.ChangeType (オブジェクト値、型 conversionType、IFormatProvider プロバイダー) で MS.Internal.Data.SystemConvertConverter.ConvertBack (オブジェクト o、型の種類、オブジェクト パラメーター、CultureInfo カルチャ) で System.Windows.Data.BindingExpression.ConvertBackHelper ( IValueConverter コンバーター、オブジェクト値、型 sourceType、オブジェクト パラメーター、CultureInfo カルチャ)」

TextBox の元の Text プロパティが文字列であるためかもしれませんが、わかりません。それを手伝ってください。

4

1 に答える 1

1

あなたはこれについて間違った方法で進んでいます。TextBoxの入力を数値のみに制限していません。フレームワークは、プロパティに適合するようにastringを anに変換しようとしていますが、エラーが示すように:入力文字列は正しい形式ではありませんでした。、例えば。ではありません。代わりにこれをコンストラクターに追加してみてください。intnew int Textint

PreviewTextInput += new TextCompositionEventHandler((s, e) => e.Handled = 
    !e.Text.All(c => Char.IsNumber(c) && c != ' '));
PreviewKeyDown += new KeyEventHandler((s, e) => e.Handled = e.Key == Key.Space);

これらは、数値以外の値が入力された場合に設定e.Handledするだけで機能しtrue、これらの場合は入力を無視する効果があります。

また、独自のプロパティを実装する必要はありませんText...これは混乱を招くだけです。元のものを使用して、int必要な場所で値を解析して、数値であること確認してください。これらの 2 つのハンドラーがそれを保証する必要があると思います。何か問題がありましたらお知らせください。

もう 1 つのアイデアは、AttachedPropertyこれらのハンドラーを使用して単純に を作成し、それを任意のTextBoxコントロールに適用することです。もちろん、プロパティも同様に実装する必要がありますMinimumMaximumAttachedProperties次のようにすることもできます。

<TextBox Text={Binding Test} Attached:TextBoxProperties.IsNumeric="True" 
    Attached:TextBoxProperties.Minimum="0" Attached:TextBoxProperties.Maximum="100" />

詳細については、MSDN の添付プロパティの概要ページを参照してください。

更新 >>>

ユーザーが から最後の文字を削除できないようにする場合TextBoxは、ハンドラーの 1 つを変更して許可しないようにします。

PreviewKeyDown += PreviewKeyDown;
...
private void PreviewKeyDown(object sender, KeyEventArgs e)
{
    TextBox textBox = sender as TextBox;
    e.Handled = e.Key == Key.Space || 
    (textBox.Text.Length == 1 && (e.Key == Key.Delete || e.Key == Key.Back));
}
于 2013-10-06T14:46:52.393 に答える