Laden...

Nur Zahlen und Sonderzeichen in TextBox zulassen

Erstellt von rs4 vor 19 Jahren Letzter Beitrag vor 12 Jahren 17.032 Views
R
rs4 Themenstarter:in
87 Beiträge seit 2005
vor 19 Jahren
Nur Zahlen und Sonderzeichen in TextBox zulassen

Hallo zum 3.

Ich kann heute einfach nicht aufhören....

Ich versuche momentan eine Textbox zu erstellen, in welcher ich nur Zahlen, bzw. Sonderzeichen einfügen kann.

Dies war mal meine Überlegung:

if(this.Datatype1 == "System.Double")
			{
				if(!Char.IsDigit(e.KeyChar) || !Char.IsPunctuation(e.KeyChar))
					e.Handled = true;
				
				if(e.Handled == true)
					this.textBox1.Clear();	
			}

Nun stellen sich zwei Probleme:

  1. Es läuft nicht, entweder ich kann nach Zahlen, oder nach Sonderzeichen suchen, also diese abfragen, aber beides in einer OR-Verknüpfung bring ich nicht hin.

  2. Anstatt clear(), hätte ich gerne, falls eine falsche Eingabe geschieht, dass es mir nur das letzte Zeichen der Textbox löscht...

Kann mir jemand bei einem meiner 2 Probelem helfen??

Wäre super!

Grüsse

D
29 Beiträge seit 2005
vor 19 Jahren

Also :

für Dein zweites Problem würde ich folgendes machen :


string oldText = TextBox1.Text;
TextBox1.Text = oldText.Remove(oldText.Length - 2, 1);

ich würde die Zeichen ganz allgemein schon im KeyPressed-Event der TextBox behandeln, dann sparst Du Dir das TextBox zurücksetzen.

zu deinem ersten Problem :

if(!Char.IsDigit(e.KeyChar) || !Char.IsPunctuation(e.KeyChar))

muss heissen :

if(!Char.IsDigit(e.KeyChar) && !Char.IsPunctuation(e.KeyChar))

ciao ciao DaSumpf

R
rs4 Themenstarter:in
87 Beiträge seit 2005
vor 19 Jahren

Wow, es läuft.

Das mit dem AND...na ja, ist eher peinlich, aber nun logisch....

Das mit dem Remove kannte ich nicht, aber ist gut zu wissen. Das brauche ich sicherlich wieder einmal!

Danke für deine rasche Hilfe!!

Geht bestimmt nicht lange, und ich stehe wieder wo an... 😁

Gruss

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo Community,

das ist ja passend. So eine (ähnliche) TextBox habe ich auch gerade erstellt. Das Problem mit dem Ansatz nur die "richtigen" Zeichen bei KeyDown o.ä. zu zulassen ist, dass er zu restriktiv ist. So werden z.B. die Cursortasten (und nicht nur die) funktionsunfähig.

Meine Textbox macht das quasi anders herum. Erstmal alles zulassen und nur bei Textänderungen gucken, ob sich ein ungewolltes Zeichen eingeschlichen hat. Wenn ja, den vorigen Zustand wiederherstellen. (Leider muss man für diesen vorigen Zustand dann doch wieder an KeyDown/KeyUp lauschen.)

Ich würde gerne mit Euch tauschen. 🙂 Ich schenke Euch die Klasse und ihr sagt mir dafür, ob ihr noch irgendwelche Problem seht oder findet bzw. welche Verbesserungsvorschläge ihr habt. Deal?


public class AllowedCharsTextBox : TextBox
{
   private String _strAllowedChars           = "-0123456789,";
   private String _strLastValidText          = "";
   private int    _iLastValidSelectionStart  = 0;
   private int    _iLastValidSelectionLength = 0;
   private bool   _fValidating               = false;

   public AllowedCharsTextBox ()
   {
   }

   public String AllowedChars
   {
      get { return _strAllowedChars; }
      set { _strAllowedChars = value; }
   }

   protected override void OnTextChanged (EventArgs e)
   {
      if (_fValidating) { return; }
      try {
         _fValidating = true;

         foreach (char ch in Text) {
            if (_strAllowedChars.IndexOf (ch) < 0) {
               Text            = _strLastValidText;
               SelectionStart  = _iLastValidSelectionStart;
               SelectionLength = _iLastValidSelectionLength;
               return;
            }
         }
         _strLastValidText = Text;
         _iLastValidSelectionStart  = SelectionStart;
         _iLastValidSelectionLength = SelectionLength;
         base.OnTextChanged (e);
      }
      finally {
         _fValidating = false;
      }
   }

   protected override void OnClick (EventArgs e)
   {
      _iLastValidSelectionStart  = SelectionStart;
      _iLastValidSelectionLength = SelectionLength;
      base.OnClick (e);
   }

   protected override void OnKeyDown (KeyEventArgs ke)
   {
      if (Text == _strLastValidText) {
         _iLastValidSelectionStart  = SelectionStart;
         _iLastValidSelectionLength = SelectionLength;
      }
      base.OnKeyDown (ke);
   }

   protected override void OnKeyUp (KeyEventArgs ke)
   {
      if (Text == _strLastValidText) {
         _iLastValidSelectionStart  = SelectionStart;
         _iLastValidSelectionLength = SelectionLength;
      }
      base.OnKeyUp (ke);
   }
}

Achso, weil jeweils der ganze Text auf ungültige Zeichen abgesucht wird, eigent sich die Box für lange Texte (Multiline) wohl eher nicht.

herbivore

T
41 Beiträge seit 2004
vor 19 Jahren

hi leute.

genau dieses problem hab ich früher schon einmal behandeln müssen, weiss aber nicht mehr genau wies ging.

wenn du jedes eingetippte zeichen so schnell wie möglich einzeln prüfen willst, dann finde ich den code meines vorposters recht cool. hab mir auch gedacht "ja dann könnt ich pfeiltasten usw ja auch verwenden"....also das ganze andersherum implementiert.

wenn du allerdings den ganzen eingegebenen string prüfen willst...ob er ne bestimmte form hat usw...dann würd ich eher auf die ereignisse und properties CausesValidation, Validating usw zielen. da kann man dann reguläre ausdrücke verwenden. die habens in sich. =)

mfg
tom

R
rs4 Themenstarter:in
87 Beiträge seit 2005
vor 19 Jahren

ja, das sieht echt gut aus...

Für mich noch etwas komplex, aber ich versuche das alles mal in Ruhe anzuschauen, mal sehen ob ich dann alles verstehe.

Danke jedenfalls für den Post!

Grüsse

C
103 Beiträge seit 2007
vor 15 Jahren

Hallo herbivore,

danke für die Klasse, genau über sowas hab ich auch einige Zeit gebrütet und nichts hingekriegt, was mich selber wirklich zufriedengestellt hätte. Du wolltest noch Verbesserungsvorschläge haben, falls einem welche einfallen 😉

Ich würde gerne mit Euch tauschen. 🙂 Ich schenke Euch die Klasse und ihr sagt mir dafür, ob ihr noch irgendwelche Problem seht oder findet bzw. welche Verbesserungsvorschläge ihr habt. Deal?

Ich würde mir irgendwann in C# mal wünschen, dass man der textbox noch sagen kann, wie der eingegebene Text genau aussehen darf. In der Sprache VFP gibts sowas, das schimpft sich InputMask. Das wirkt sich in dem Sinne aus, dass man eben beispielsweise definiert, dass genau 10 Stellen eingegeben werden können, dann kommt meinetwegen ein Komma und dann noch 2 Stellen (Sinnvoll bei Eingabe von Geldbeträgen). Die InputMask hat man da als String angegeben, das sah so aus: "##########,##" (jede # steht für eine Ziffer, es sind auch nur Ziffern oder ein führendes Minuszeichen erlaubt). Die Textbox war dann auch so schlau, dass sie evtl übrige Felder vor dem Komma ignoriert hat, sobald mal ein Komma eingegeben war. Also egal, ob man die 10 Stellen vor dem Komma ausgereizt hat oder nicht, das Komma war bei so einer InputMask immer das drittletzte Zeichen. Man kann dabei auch nicht versehentlich 2 Kommas eingeben.

Mit einer anderen InputMask konnte man ein Feld ganz leicht zum Datumsfeld machen: "##.##.####". Diese Inputmask erzwingt an den richtigen Stellen die Trennpunkte (gibt man 3 Ziffern nacheinander ein, wird zwischen der 2. und der 3. automatisch der Punkt eingefügt), und lässt dazwischen nur Ziffern zu.

Das wäre mein Verbesserungsvorschlag. Oder lässt sich sowas schon von Haus aus mit .NET Bordmitteln relativ unkompliziert erreichen?

Freundliche Grüße,
capcom

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo capcom,

dafür gibt es in .NET MaskedTextBox.

herbivore

B
54 Beiträge seit 2008
vor 14 Jahren

okay, also erstmal vielen Danke für die Gute Klasse.
Ich habe damit aber ein kleines Problem, dass ich nicht verstehe.

Also ich gehe so vor, dass ich normale Textboxen erstelle und dann im Formdesigner an beiden Stellen einfach den Typ ändere. Das funktioniert dann auch so weit. Nur, wenn ich jetzt die erlaubten Zeichen ändere, in meinem Fall ein "E" hinzufüge, dann wird das nicht übernommen für die alten Textboxen. Wenn ich jetzt aber wie oben beschrieben eine neue Textbox erstelle und diese dann entsprechend ändere , dann funktioniert das neue Zeichen bei dieser neuen Textbox. Ich habe dann also zwei Textboxen, die von der gleichen Klasse sind aber unterschiedlich funktionieren, die vor der Änderung erstellte Textbox akzeptiert das neue Zeichen nicht, die neue schon. Kann mir das jemand erklären?
Und noch eine zweite Frage, das Symbol der Klasse ist nicht das gewohnte Symbol sondern ziemlich komisch (kann es nicht beschreiben). Woran liegt das?
liebe Grüße

F
1 Beiträge seit 2010
vor 13 Jahren

@ herbivore

Also ein paar kleine Verbesserunge hätte ich da schon noch für dich:

Man kann dein "-" an jeder beliebigen Stelle angeben.
Es stört die NumBox auch nicht wirklich wenn man mehrere Kommas eingibt 😉

Was ich nicht ganz verstehe, warum du auch die anderen Methoden überschrieben hast.

Bei mir klappt das auch ganz gut so:


public class NumberBox : TextBox
    {
        const string NUMBERS = "01234567890,-";

        private bool isValidating = false;
        private string lastValdatedText = String.Empty;

        public NumberBox()
            : base()
        { }

        protected override void OnTextChanged(EventArgs e)
        {
            bool isKommaFound = false;

            if (isValidating) return;

            try
            {
                isValidating = true;
                char ch;

                for (int i = 0; i < Text.Length; i++)
                {
                    ch = Text[i];
                    //MessageBox.Show(Text.IndexOf(ch).ToString());


                    if (NUMBERS.IndexOf(ch) < 0)        // Nur Zugelassene Zahlen annehmen
                    {
                        ignoreChar();
                        return;
                    }

                    if (ch == '-' && i != 0)            // Minus darf nur an erster Positon stehen
                    {
                        ignoreChar();
                        return;
                    }

                    if (ch == ',')
                    {
                        if (isKommaFound)               // Wenn Komma schon vorhanden ist
                        {
                            ignoreChar();
                            return;
                        }
                        else                            // Wenn Komma noch nicht vorhanden ist
                        {
                            isKommaFound = true;
                        }

                        if (i == 0)                     // Wenn Komma an der ersten Stelle steht
                        {
                            this.Text = "0,";
                            this.SelectionStart = this.Text.Length;
                            return;
                        }
                    }

                }

                lastValdatedText = this.Text;
            }

            finally
            {
                isValidating = false;
            }

            base.OnTextChanged(e);
        }

        private void ignoreChar()
        {
            this.Text = lastValdatedText;
            this.SelectionStart = lastValdatedText.Length;
            //this.SelectionLength = _iLastValidSelectionLength;
            return;

        }

Wem dazu noch was einfällt, immer her damit

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo Flobby,

Was ich nicht ganz verstehe, warum du auch die anderen Methoden überschrieben hast.

gib mal ein paar Ziffern ein, markiere dann einige davon und drücke dann eine nicht erlaubte Taste, z.B. einen Buchstaben. In deiner Box verschwindet die Selektion, bei meiner bleibt sie erhalten. Außerdem springt bei dir der Cursor bei einer Fehleingabe ans Ende des Textes. Beim mir bleibt der Cursor an der richtigen Position stehen.

Also ein paar kleine Verbesserunge hätte ich da schon noch für dich:

Aus meiner Sicht sind das keine Verbesserungen. Meine TextBox heißt ja auch absichtlich AllowedCharsTextBox und nicht NumberBox, weil ich gar nicht erzwingen will, dass zu jedem Zeitpunkt eine gültige Zahl in der Box steht, letztlich geht das auch gar nicht (s.u.). Meine Box ist außerdem nicht auf Zahlen beschränkt, sondern kann beliebige Zeichen zulassen.

Es ist immer die Frage, wie weit man den Benutzer einschränken will. Meine Klasse ist in dieser Hinsicht wohl schon ein ziemlich guter Kompromiss. Wie ich in [FAQ] In einer TextBox nur bestimmte Zeichen/Eingaben zulassen schrieb:

Bei alle dem sollte man auch noch berücksichtigen, dass während der Eingabe und besonders beim Editieren eines am Ende gültigen Werts oft ungültige Zwischenzustände entstehen können. Wenn man erzwingen will, dass zu jedem Zeitpunkt in der TextBox ein gültiger Wert ist, dann kann dadurch die Eingabe bzw. das Editieren sehr erschwert oder im Extremfall gar verhindert werden.

Deshalb bin ich dagegen zu erzwingen, dass man ein Minus nur am Anfang und dass man keine zwei Kommas eingeben kann.

Wenn du eine gute NumberBox schreiben willst, musst du zuerst die Probleme mit der Selektion und der CursorPosition in den Griff bekommen. Dann sollte beim Drücken von Minus egal an welcher Stelle das Vorzeichen (auf Minus) geändert werden und beim Drücken von Plus egal an welcher Stelle ein etwaiges Vorzeichen entfernt werden. Beim Drücken von Komma egal an welcher Stelle, sollte das alte Komma entfernt werden und nur das neue Komma stehen bleiben. Die führende Null kannst du dann ja gerne davor setzen, solltest sie dann aber auch wieder entfernen, wenn das Komma erneut versetzt wird.

Du musst dir aber im Klaren sein, dass selbst dann nicht sichergestellt ist, dass nur gültige Zahlen eingegeben werden, denn er erfolgt ja keine Prüfung des zulässigen Wertebereichs. Man kann also immer noch eine Zahl eingeben, die bei anschließenden Parse einen Fehler verursacht, obwohl das Format stimmt, aber eben nicht der Wertebereich.

Wenn man auf die Idee kommt, die Prüfung des Wertebereichs on-the-fly zu machen, kommt man erst recht in die eben beschriebenen Probleme einen Wert zu ändern, ohne dabei ungültige Zwischenzuständen zu erzeugen. Soll der Wertebereich z.B. zwischen 20 und 100 liegen, und es ist 20 im Feld eingegeben, aber ich möchte gerne 100 darin stehen haben, dann geht das (von der Zwischenablage mal abgesehen) nicht ohne einen ungültigen Zwischenzustand. Wenn man versucht an die 20 eine Null anzuhängen, um danach aus der 2 eine 1 zu machen, wäre die zwischenzeitlich entstehende 200 zu groß, versucht man daher zuerst aus der 2 eine 1 zumachen, um dann die Null anhängen zu können, wäre die zwischenzeitlich entstehende 10 zu klein.

Eine NumberBox, die alles schon während der Eingabe prüft, ist unpraktikabel. Es bleibt also immer etwas, was man nachträglich prüfen muss. Deshalb denke ich, dass die AllowedCharsTextBox ein guter Kompromiss zwischen on-the-fly-Prüfung und nachträglicher Prüfung ist, die viele Fehleingabe vermeidet ohne den Benutzer zu sehr einzuschränken.

herbivore

W
2 Beiträge seit 2011
vor 12 Jahren

...Ich schenke Euch die Klasse und ihr sagt mir dafür, ob ihr noch irgendwelche Problem seht oder findet bzw. welche Verbesserungsvorschläge ihr habt. Deal?

"Der Startbeitrag ist älter als 6 Jahre." Das war die Zeit meines Studiums, damals waren die Globalisierungsgegner in aller Munde. Bist wohl auch einer von denen 😉


private String _strAllowedChars           = "0123456789" + System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator + System.Globalization.NumberFormatInfo.CurrentInfo.NegativeSign;

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo W.Nickel,

du hast Recht, das ist eine sinnvolle Ergänzung/Änderung. Vielen Dank!

herbivore