WPF में केवल संख्यात्मक इनपुट स्वीकार करने के लिए मैं टेक्स्टबॉक्स कैसे प्राप्त करूं?




xaml textbox (18)

अब मुझे पता है कि इस प्रश्न का एक स्वीकार्य उत्तर है , लेकिन व्यक्तिगत रूप से, मुझे थोड़ा उलझन लगता है और मुझे विश्वास है कि इससे इससे आसान होना चाहिए। इसलिए मैं यह दिखाने की कोशिश करूंगा कि मैं इसे कैसे काम कर सकता हूं जैसा कि मैं कर सकता हूं:

WinForms में , KeyPress नामक एक ईवेंट है जो इस तरह के कार्य के लिए बिल्कुल अच्छा है। लेकिन यह WPF में मौजूद नहीं है, इसलिए इसके बजाय, हम PreviewTextInput ईवेंट का उपयोग करेंगे। इसके अलावा, सत्यापन के लिए, मेरा मानना ​​है कि कोई textbox.Text माध्यम से लूप को textbox.Text उपयोग कर सकता है। textbox.Text और जांचें कि यह मेल खाता है ;) स्थिति, लेकिन ईमानदारी से, यह नियमित अभिव्यक्तियों के लिए है।

पवित्र कोड में गोता लगाने से पहले एक और बात; घटना को निकालने के लिए, कोई दो चीजें कर सकता है:

  1. प्रोग्राम को बताने के लिए प्रोग्राम को बताने के लिए xaml का उपयोग करें: <PreviewTextInput="textBox_PreviewTextInput/>
  2. इसे फॉर्म की Loaded घटना में करें (जिसमें textBox.PreviewTextInput += onlyNumeric; ): textBox.PreviewTextInput += onlyNumeric;

मुझे लगता है कि दूसरी विधि बेहतर है क्योंकि इस तरह की स्थितियों में, आपको अधिकतर एक ही शर्त ( regex ) को एक से अधिक regex पर लागू करने की आवश्यकता होगी और आप स्वयं को दोहराना नहीं चाहते हैं!

अंत में, यहां बताया गया है कि आप इसे कैसे करेंगे:

private void onlyNumeric(object sender, TextCompositionEventArgs e)
{
    string onlyNumeric = @"^([0-9]+(.[0-9]+)?)$";
    Regex regex = new Regex(onlyNumeric);
    e.Handled = !regex.IsMatch(e.Text);
}

चीयर्स!

मैं अंक और दशमलव बिंदु स्वीकार करने के लिए देख रहा हूं, लेकिन कोई संकेत नहीं।

मैंने WinForms के लिए न्यूमेरिक अपडाउन नियंत्रण का उपयोग करके नमूनों को देखा है, और माइक्रोसॉफ्ट से न्यूमेरिक अपडाउन कस्टम कंट्रोल का यह नमूना देखा है। लेकिन अब तक ऐसा लगता है कि न्यूमेरिक अपडाउन (डब्ल्यूपीएफ द्वारा समर्थित है या नहीं) वह कार्यक्षमता प्रदान करने वाला नहीं है जो मैं चाहता हूं। जिस तरह से मेरा ऐप डिज़ाइन किया गया है, कोई भी उनके सही दिमाग में तीर से गड़बड़ नहीं करना चाहता है। वे मेरे ऐप के संदर्भ में कोई व्यावहारिक अर्थ नहीं बनाते हैं।

तो मैं एक मानक WPF टेक्स्टबॉक्स को केवल उन पात्रों को स्वीकार करने का एक आसान तरीका ढूंढ रहा हूं जो मैं चाहता हूं। क्या यह संभव है? क्या यह व्यावहारिक है?


इवेंट हैंडलर पूर्वावलोकन पाठ इनपुट है। यहां नियमित अभिव्यक्ति केवल टेक्स्ट इनपुट से मेल खाती है यदि यह संख्या नहीं है, तो यह प्रवेश टेक्स्टबॉक्स में नहीं बनाई गई है। यदि आप केवल अक्षर चाहते हैं तो नियमित अभिव्यक्ति को [^a-zA-Z] के रूप में बदलें।

XAML

<TextBox Name="NumberTextBox" PreviewTextInput="NumberValidationTextBox"/>

XAML.CS फ़ाइल

using System.Text.RegularExpressions;
private void NumberValidationTextBox(object sender, TextCompositionEventArgs e)
{
    Regex regex = new Regex("[^0-9]+");
    e.Handled = regex.IsMatch(e.Text);
}

एक वैल्यूएशन नियम में जोड़ें कि जब टेक्स्ट यह निर्धारित करने के लिए चेक बदलता है कि डेटा संख्यात्मक है या नहीं, और यदि यह है, तो प्रसंस्करण जारी रखने की अनुमति देता है, और यदि ऐसा नहीं है, तो उपयोगकर्ता को संकेत मिलता है कि उस क्षेत्र में केवल संख्यात्मक डेटा स्वीकार किया जाता है।

यहां और पढ़ें: http://www.codeproject.com/KB/WPF/wpfvalidation.aspx


एक सत्यापन नियम को भी लागू कर सकता है और इसे टेक्स्टबॉक्स पर लागू कर सकता है:

  <TextBox>
    <TextBox.Text>
      <Binding Path="OnyDigitInput" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
        <Binding.ValidationRules>
          <conv:OnlyDigitsValidationRule />
        </Binding.ValidationRules>
      </Binding>
    </TextBox.Text>

अनुसरण के नियम के कार्यान्वयन के साथ (अन्य उत्तरों में प्रस्तावित एक ही रेगेक्स का उपयोग करके):

public class OnlyDigitsValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        var validationResult = new ValidationResult(true, null);

        if(value != null)
        {
            if (!string.IsNullOrEmpty(value.ToString()))
            {
                var regex = new Regex("[^0-9.-]+"); //regex that matches disallowed text
                var parsingOk = !regex.IsMatch(value.ToString());
                if (!parsingOk)
                {
                    validationResult = new ValidationResult(false, "Illegal Characters, Please Enter Numeric Value");
                }
            }
        }

        return validationResult;
    }
}

कुछ ऐसा पहले से ही इस्तेमाल किया गया था और एक व्यवहार का उपयोग करके इस पर अपना खुद का मोड़ लगाया गया है, इसलिए मुझे दृश्यों के एक टन में इस कोड को प्रचारित करने की ज़रूरत नहीं है ...

public class AllowableCharactersTextBoxBehavior : Behavior<TextBox>
{
    public static readonly DependencyProperty RegularExpressionProperty =
         DependencyProperty.Register("RegularExpression", typeof(string), typeof(AllowableCharactersTextBoxBehavior),
         new FrameworkPropertyMetadata(".*"));
    public string RegularExpression
    {
        get
        {
            return (string)base.GetValue(RegularExpressionProperty);
        }
        set
        {
            base.SetValue(RegularExpressionProperty, value);
        }
    }

    public static readonly DependencyProperty MaxLengthProperty =
        DependencyProperty.Register("MaxLength", typeof(int), typeof(AllowableCharactersTextBoxBehavior),
        new FrameworkPropertyMetadata(int.MinValue));
    public int MaxLength
    {
        get
        {
            return (int)base.GetValue(MaxLengthProperty);
        }
        set
        {
            base.SetValue(MaxLengthProperty, value);
        }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewTextInput += OnPreviewTextInput;
        DataObject.AddPastingHandler(AssociatedObject, OnPaste);
    }

    private void OnPaste(object sender, DataObjectPastingEventArgs e)
    {
        if (e.DataObject.GetDataPresent(DataFormats.Text))
        {
            string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));

            if (!IsValid(text, true))
            {
                e.CancelCommand();
            }
        }
        else
        {
            e.CancelCommand();
        }
    }

    void OnPreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
    {
        e.Handled = !IsValid(e.Text, false);
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.PreviewTextInput -= OnPreviewTextInput;
        DataObject.RemovePastingHandler(AssociatedObject, OnPaste);
    }

    private bool IsValid(string newText, bool paste)
    {
        return !ExceedsMaxLength(newText, paste) && Regex.IsMatch(newText, RegularExpression);
    }

    private bool ExceedsMaxLength(string newText, bool paste)
    {
        if (MaxLength == 0) return false;

        return LengthOfModifiedText(newText, paste) > MaxLength;
    }

    private int LengthOfModifiedText(string newText, bool paste)
    {
        var countOfSelectedChars = this.AssociatedObject.SelectedText.Length;
        var caretIndex = this.AssociatedObject.CaretIndex;
        string text = this.AssociatedObject.Text;

        if (countOfSelectedChars > 0 || paste)
        {    
            text = text.Remove(caretIndex, countOfSelectedChars);
            return text.Length + newText.Length;
        }
        else
        {
            var insert = Keyboard.IsKeyToggled(Key.Insert);

            return insert && caretIndex < text.Length ? text.Length : text.Length + newText.Length;
        }
    }
}

प्रासंगिक दृश्य कोड यहां दिया गया है।

<TextBox MaxLength="50" TextWrapping="Wrap" MaxWidth="150" Margin="4"
 Text="{Binding Path=FileNameToPublish}" >
     <interactivity:Interaction.Behaviors>
         <v:AllowableCharactersTextBoxBehavior RegularExpression="^[0-9.\-]+$" MaxLength="50" />
     </interactivity:Interaction.Behaviors> 
</TextBox>

डब्ल्यूपीएफ आवेदन में, आप टेक्स्ट चेंज किए गए ईवेंट को संभालने से इसे संभाल सकते हैं:

void arsDigitTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
    Regex regex = new Regex("[^0-9]+");
    bool handle = regex.IsMatch(this.Text);
    if (handle)
    {
        StringBuilder dd = new StringBuilder();
        int i = -1;
        int cursor = -1;
        foreach (char item in this.Text)
        {
            i++;
            if (char.IsDigit(item))
                dd.Append(item);
            else if(cursor == -1)
                cursor = i;
        }
        this.Text = dd.ToString();

        if (i == -1)
            this.SelectionStart = this.Text.Length;
        else
            this.SelectionStart = cursor;
    }
}

मैंने numpad संख्याओं और बैकस्पेस की अनुमति दी:

    private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        int key = (int)e.Key;

        e.Handled = !(key >= 34 && key <= 43 || 
            key >= 74 && key <= 83 || key == 2);
    }

आशा करता हूँ की ये काम करेगा।


यदि आप मूल कार्य करने के लिए बहुत सारे कोड लिखना नहीं चाहते हैं (idk क्यों लोग लंबी विधियां करते हैं) जब आप ऐसा कर सकते हैं:

  1. नामस्थान जोड़ें:

    using System.Text.RegularExpressions;
    
  2. Xaml में एक टेक्स्ट चेंज संपत्ति सेट करें:

    <TextBox x:Name="txt1" TextChanged="txt1_TextChanged"/>
    
  3. Txt1_TextChanged विधि के तहत WPF में, Regex जोड़ें। बदलें

    private void txt1_TextChanged(object sender, TextChangedEventArgs e)
    {
        txt1.Text = Regex.Replace(txt1.Text, "[^0-9]+", "");
    }
    

यह एक पुराना सवाल है, लेकिन कुछ समय के लिए यहां कुछ समाधानों का उपयोग करने के बाद, मैंने अपना खुद का विकास किया जो मेरे एमवीवीएम सेटअप के लिए अच्छा काम करता है। ध्यान दें कि यह कुछ अन्य लोगों के रूप में गतिशील नहीं है क्योंकि अभी भी उपयोगकर्ताओं को गलत वर्ण दर्ज करने की इजाजत है, लेकिन यह उन्हें बटन दबाकर और कुछ भी करने से रोकता है। क्रियाओं को निष्पादित नहीं किया जा सकता है जब यह बटन बाहर ग्रेइंग के मेरे विषय के साथ अच्छी तरह से चला जाता है।

मेरे पास एक TextBox है जिसे उपयोगकर्ता को मुद्रित करने के लिए कई दस्तावेज़ पृष्ठ दर्ज करना होगा:

<TextBox Text="{Binding NumberPagesToPrint, UpdateSourceTrigger=PropertyChanged}"/>

... इस बाध्यकारी संपत्ति के साथ:

private string _numberPagesToPrint;
public string NumberPagesToPrint
{
    get { return _numberPagesToPrint; }
    set
    {
        if (_numberPagesToPrint == value)
        {
            return;
        }

        _numberPagesToPrint = value;
        OnPropertyChanged("NumberPagesToPrint");
    }
}

मेरे पास एक बटन भी है:

<Button Template="{DynamicResource CustomButton_Flat}" Content="Set"
        Command="{Binding SetNumberPagesCommand}"/>

... इस आदेश के साथ बाध्यकारी:

private RelayCommand _setNumberPagesCommand;
public ICommand SetNumberPagesCommand
{
    get
    {
        if (_setNumberPagesCommand == null)
        {
            int num;
            _setNumberPagesCommand = new RelayCommand(param => SetNumberOfPages(),
                () => Int32.TryParse(NumberPagesToPrint, out num));
        }

        return _setNumberPagesCommand;
    }
}

और फिर SetNumberOfPages() की विधि है, लेकिन यह इस विषय के लिए महत्वहीन है। कुछ समाधान कुछ स्थितियों में दूसरों की तुलना में बेहतर होते हैं, इसलिए मैंने सोचा कि मैं इसे साझा करूंगा, ताकि कोई भी जो मेरी समान स्थिति में हो, उसका उपयोग कर सके। यह मेरे मामले में अच्छी तरह से काम करता है क्योंकि मुझे व्यू कोड के पीछे कोड में कोई कोड जोड़ने की ज़रूरत नहीं है और यह मुझे Command प्रॉपर्टी का उपयोग करके व्यवहार को नियंत्रित करने की अनुमति देता है।


यह एक पुराना सवाल है, लेकिन मैं एक साधारण परियोजना के लिए एक अनबाउंड बॉक्स के साथ काम कर रहा था जिस पर मैं काम कर रहा था, इसलिए मैं मानक बाध्यकारी दृष्टिकोण का उपयोग नहीं कर सका। नतीजतन मैंने एक साधारण हैक बनाया जो दूसरों को मौजूदा टेक्स्टबॉक्स नियंत्रण को विस्तारित करके काफी आसान हो सकता है:

namespace MyApplication.InterfaceSupport
{
    public class NumericTextBox : TextBox
    {
        public NumericTextBox() : base()
        {
            TextChanged += OnTextChanged;
        }


        public void OnTextChanged(object sender, TextChangedEventArgs changed)
        {

            if (!String.IsNullOrWhiteSpace(Text))
            {
                try
                {
                    int value = Convert.ToInt32(Text);
                }
                catch (Exception e)
                {
                    MessageBox.Show(String.Format("{0} only accepts numeric input.", Name));
                    Text = "";
                }
            }
        }

        public int? Value
        {
            set
            {
                if (value != null)
                {
                    this.Text = value.ToString();
                }
                else Text = "";
            }
            get
            {
                try
                {
                    return Convert.ToInt32(this.Text);
                }
                catch (Exception ef)
                {
                    // not numeric.
                }
                return null;
            }
        }



    }
}

जाहिर है, एक फ्लोटिंग प्रकार के लिए, आप इसे एक फ्लोट के रूप में पार्स करना चाहते हैं और इसी तरह। सिद्धांत लागू होते हैं।

फिर XAML फ़ाइल में आपको प्रासंगिक नामस्थान शामिल करने की आवश्यकता है:

<UserControl x:Class="MyApplication.UserControls.UnParameterisedControl"
             [ Snip ]
             xmlns:interfaceSupport="clr-namespace:MyApplication.InterfaceSupport"
             >

इसके बाद आप इसे नियमित नियंत्रण के रूप में उपयोग कर सकते हैं:

<interfaceSupport:NumericTextBox Height="23" HorizontalAlignment="Left" Margin="168,51,0,0" x:Name="NumericBox" VerticalAlignment="Top" Width="120" >

यहां मेरे पास @ रे के जवाब से प्रेरित एक सरल समाधान है। यह संख्या के किसी भी रूप की पहचान करने के लिए पर्याप्त होना चाहिए।

यदि आप केवल सकारात्मक संख्या, पूर्णांक मान या मूल्यों को अधिकतम दशमलव स्थानों आदि के लिए सटीक मानना ​​चाहते हैं, तो यह समाधान भी आसानी से संशोधित किया जा सकता है।

जैसा कि रे के उत्तर द्वारा सुझाया गया है, आपको पहले PreviewTextInput ईवेंट जोड़ने की आवश्यकता है:

<TextBox PreviewTextInput="TextBox_OnPreviewTextInput"/>

फिर निम्नलिखित कोड में निम्नलिखित डालें:

private void TextBox_OnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
    var s = sender as TextBox;
    // use SelectionStart property to find the caret position
    // insert the previewed text into the existing text in the textbox
    var text = s.Text.Insert(s.SelectionStart, e.Text);

    double d;
    // if parsing is successful, set Handled to false
    e.Handled = !double.TryParse(text, out d);
}

विंडोज़ फॉर्म में यह आसान था, आप KeyPress के लिए एक ईवेंट जोड़ सकते हैं और सबकुछ आसानी से काम करता है। हालांकि, डब्ल्यूपीएफ में वह घटना नहीं है। लेकिन इसके लिए एक आसान तरीका है।

डब्ल्यूपीएफ टेक्स्टबॉक्स में टेक्स्ट चेंजेड इवेंट है जो सब कुछ के लिए सामान्य है, इसमें पेस्टिंग, टाइपिंग और जो कुछ भी आपके दिमाग में आ सकता है।

तो आप ऐसा कुछ कर सकते हैं:

XAML:

<TextBox name="txtBox1" ... TextChanged="TextBox_TextChanged"/>

कोड के पीछे:

private void TextBox_TextChanged(object sender, TextChangedEventArgs e) {
        string s = Regex.Replace(((TextBox)sender).Text, @"[^\d.]", "");
        ((TextBox)sender).Text = s;
    }

यह भी स्वीकार करता है . , अगर आप इसे नहीं चाहते हैं, तो इसे regex कथन से हटाएं @[^\d]

नोट : इस ईवेंट का उपयोग कई टेक्स्टबॉक्स पर किया जा सकता है क्योंकि यह sender ऑब्जेक्ट के टेक्स्ट का उपयोग करता है। आप केवल एक बार ईवेंट लिखते हैं और एकाधिक टेक्स्टबॉक्स के लिए इसका उपयोग कर सकते हैं।


संख्या मूल्य की जांच करते समय आप VisualBasic.IsNumeric फ़ंक्शन का उपयोग कर सकते हैं


हम पाठ बॉक्स में परिवर्तित घटना पर सत्यापन कर सकते हैं। निम्नलिखित कार्यान्वयन संख्यात्मक और एक दशमलव बिंदु के अलावा कुंजीपटल इनपुट रोकता है।

private void textBoxNumeric_TextChanged(object sender, TextChangedEventArgs e) 
{         
      TextBox textBox = sender as TextBox;         
      Int32 selectionStart = textBox.SelectionStart;         
      Int32 selectionLength = textBox.SelectionLength;         
      String newText = String.Empty;         
      int count = 0;         
      foreach (Char c in textBox.Text.ToCharArray())         
      {             
         if (Char.IsDigit(c) || Char.IsControl(c) || (c == '.' && count == 0))             
         {                 
            newText += c;                 
            if (c == '.')                     
              count += 1;             
         }         
     }         
     textBox.Text = newText;         
     textBox.SelectionStart = selectionStart <= textBox.Text.Length ? selectionStart :        textBox.Text.Length;     
} 

This is what I would use to get a wpf textbox that accept digits and the decimal point:

class numericTextBox : TextBox
{
    protected override void OnKeyDown(KeyEventArgs e)
    {
        bool b = false;
        switch (e.Key)
        {
            case Key.Back: b = true; break;
            case Key.D0: b = true; break;
            case Key.D1: b = true; break;
            case Key.D2: b = true; break;
            case Key.D3: b = true; break;
            case Key.D4: b = true; break;
            case Key.D5: b = true; break;
            case Key.D6: b = true; break;
            case Key.D7: b = true; break;
            case Key.D8: b = true; break;
            case Key.D9: b = true; break;
            case Key.OemPeriod: b = true; break;
        }
        if (b == false)
        {
            e.Handled = true;
        }
        base.OnKeyDown(e);
    }
}

Put the code in a new class file, add

using System.Windows.Controls;
using System.Windows.Input;

at the top of the file and build the solution. The numericTextBox control will then appear at the top of the toolbox.


एक पूर्वावलोकन पाठ इनपुट घटना जोड़ें। ऐसा ही है: <TextBox PreviewTextInput="PreviewTextInput" />

फिर उस सेट के अंदर e.Handlede.Handled अगर पाठ की अनुमति नहीं है। e.Handled = !IsTextAllowed(e.Text);

मैं IsTextAllowed विधि में एक सरल regex का उपयोग यह देखने के लिए करता हूं कि मुझे क्या टाइप किया गया है या नहीं। मेरे मामले में मैं केवल संख्याओं, बिंदुओं और डैश की अनुमति देना चाहता हूं।

private static bool IsTextAllowed(string text)
{
    Regex regex = new Regex("[^0-9.-]+"); //regex that matches disallowed text
    return !regex.IsMatch(text);
}

यदि आप गलत डेटा के DataObject.Pasting को रोकना चाहते हैं तो DataObject.Pasting ईवेंट DataObject.Pasting="TextBoxPasting" को here दिखाए गए अनुसार (कोड उद्धृत):

// Use the DataObject.Pasting Handler 
private void TextBoxPasting(object sender, DataObjectPastingEventArgs e)
{
    if (e.DataObject.GetDataPresent(typeof(String)))
    {
        String text = (String)e.DataObject.GetData(typeof(String));
        if (!IsTextAllowed(text))
        {
            e.CancelCommand();
        }
    }
    else
    {
        e.CancelCommand();
    }
}

PreviewTextInput += (s, e) =>
{
    e.Handled = !e.Text.All(char.IsDigit);
};

e.Handled = (int)e.Key >= 43 || (int)e.Key <= 34;

टेक्स्टबॉक्स के पूर्वावलोकन कीडाउन घटना में।





numericupdown