Visual Studio C# verwendet Zustandsmaschinen, um die Eingabe in Textfelder einzuschränken. Angehängte Eigenschaften zum Einschränken der Texteingabe

Antipyretika für Kinder werden von einem Kinderarzt verschrieben. Aber es gibt Notfallsituationen für Fieber, wenn das Kind sofort Medikamente erhalten muss. Dann übernehmen die Eltern die Verantwortung und nehmen fiebersenkende Medikamente. Was darf Säuglingen gegeben werden? Wie kann man bei älteren Kindern die Temperatur senken? Welche Medikamente sind am sichersten?

WPF ist weit davon entfernt, eine neue Technologie auf dem Markt zu sein, aber relativ neu für mich. Und wie so oft beim Lernen von etwas Neuem besteht der Wunsch/die Notwendigkeit, Fahrräder mit Vierkanträdern und Leichtmetallrädern zu erfinden, um einige typische Aufgaben zu lösen.

Eine solche Aufgabe besteht darin, Benutzereingaben auf bestimmte Daten zu beschränken. Angenommen, wir möchten, dass ein Textfeld nur ganzzahlige Werte akzeptiert, ein anderes ein Datum in einem bestimmten Format akzeptiert und ein drittes nur Gleitkommazahlen akzeptiert. Die endgültige Validierung solcher Werte erfolgt natürlich weiterhin in den Ansichtsmodellen, aber solche Eingabebeschränkungen machen die Benutzeroberfläche freundlicher.

In Windows Forms war diese Aufgabe recht einfach zu lösen, und als die gleiche TextBox von DevExpress mit der eingebauten Möglichkeit verfügbar war, Eingaben mithilfe regulärer Ausdrücke einzuschränken, war alles im Allgemeinen einfach. Es gibt einige Beispiele für die Lösung des gleichen Problems in WPF, von denen die meisten auf eine von zwei Optionen hinauslaufen: die Verwendung eines TextBox-Klassenerbes oder das Hinzufügen einer angefügten Eigenschaft mit den erforderlichen Einschränkungen.

HINWEIS
Wenn dich meine Argumentation nicht sehr interessiert, du aber sofort Codebeispiele brauchst, dann kannst du entweder das gesamte Projekt herunterladen
WpfEx von GitHub , oder laden Sie die Hauptimplementierung herunter, die in enthalten ist TextBoxBehavior.cs und TextBoxDoubleValidator.cs .

Na, fangen wir an?

Da die Vererbung eine ziemlich strenge Einschränkung einführt, bevorzuge ich persönlich in diesem Fall die Verwendung angehängter Eigenschaften, da Sie mit diesem Mechanismus die Anwendung dieser Eigenschaften auf Steuerelemente eines bestimmten Typs einschränken können (ich möchte diese angehängte Eigenschaft nicht IsDouble könnte auf einen TextBlock angewendet werden, für den es keinen Sinn macht).
Außerdem ist zu beachten, dass Sie beim Einschränken der Benutzereingaben keine bestimmten Ganzzahl- und Bruchtrennzeichen (z. B. „.“ (Punkt) oder „,“ (Komma)) sowie die Zeichen „+“ und „ -', da alles von den regionalen Einstellungen des Benutzers abhängt.
Um die Möglichkeit zur Einschränkung der Dateneingabe zu implementieren, müssen wir das Benutzereingabeereignis manuell abfangen, analysieren und diese Änderungen verwerfen, wenn sie uns nicht passen. Im Gegensatz zu Windows Forms, das ein Ereignispaar verwendet XXXGeändert und XXXWechsel verwendet WPF Vorschauversionen von Ereignissen für den gleichen Zweck, die so verarbeitet werden können, dass das Hauptereignis nicht ausgelöst wird. (Ein klassisches Beispiel wäre die Behandlung von Maus- oder Tastaturereignissen, die bestimmte Tasten oder deren Kombinationen deaktivieren.)

Und alles wäre gut, wenn die TextBox-Klasse zusammen mit dem TextChanged-Ereignis auch enthalten wäre VorschauTextGeändert, die verarbeitet werden könnten und Benutzereingaben "abbrechen", wenn wir den eingegebenen Text für falsch halten. Und da es das nicht gibt, muss jeder und jede sein eigenes Lisapet erfinden.

Die Lösung des Problems

Die Lösung des Problems besteht darin, eine TextBoxBehavior-Klasse zu erstellen, die die angehängte IsDoubleProperty-Eigenschaft enthält, nach deren Einstellung der Benutzer nichts anderes als +, -, Zeichen in dieses Textfeld eingeben kann. (Ganzzahl- und Dezimaltrennzeichen) sowie Zahlen (vergessen Sie nicht, dass wir die Einstellungen des aktuellen Streams verwenden müssen und nicht die fest codierten Werte).

Öffentliche Klasse TextBoxBehavior ( // Angefügte Eigenschaft vom booleschen Typ, Einstellung, die Benutzereingaben einschränkt, öffentlich, statisch, schreibgeschützt. ; // Dieses Attribut erlaubt keine Verwendung von IsDouble mit anderen // UI-Elementen als TextBox oder seinen Nachkommen public static bool GetIsDouble(DependencyObject element) () public static void SetIsDouble(DependencyObject element, bool value) () // Aufgerufen wenn TextBoxBehavior.IsDouble="True" in XAML festgelegt ist private statische void OnIsDoubleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) ( // Street magic ) )

Die Hauptkomplexität der Handler-Implementierung VorschauTextEingabe(ebenso wie das Ereignis des Einfügens von Text aus der Zwischenablage) liegt darin, dass in den Ereignisargumenten nicht der Gesamtwert des Textes übertragen wird, sondern nur der neu eingegebene Teil davon. Daher muss der Zusammenfassungstext manuell gebildet werden, wobei die Möglichkeit der Textauswahl in der TextBox, die aktuelle Position des Cursors darin und möglicherweise der Zustand der Schaltfläche Einfügen (die wir nicht analysieren werden) berücksichtigt werden muss:

// Wird aufgerufen, wenn TextBoxBehavior.IsDouble="True" in XAML festgelegt ist private static void OnIsDoubleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) ( // Da wir unsere angefügte Eigenschaft nur auf die Klasse // TextBox oder ihre Nachkommen beschränkt haben, gilt Folgendes Transformation ist - sicher var textBox = (TextBox) d; // Jetzt müssen wir zwei wichtige Fälle behandeln: // 1. Manuelle Benutzereingabe // 2. Daten aus der Zwischenablage einfügen textBox.PreviewTextInput += PreviewTextInputForDouble; DataObject.AddPastingHandler( textBox, OnPasteForDouble ); )

TextBoxDoubleValidator-Klasse

Der zweite wichtige Punkt ist die Implementierung der Validierungslogik des neu eingegebenen Textes, für die die Methode verantwortlich ist Ist gültig separate Klasse TextBoxDoubleValidator.

bei den meisten auf einfache Weise verstehen, wie sich die Methode verhalten soll Ist gültig dieser Klasse besteht darin, einen Unit-Test dafür zu schreiben, der alle Eckfälle abdeckt (dies ist nur einer dieser Fälle, in denen parametrisierte Unit-Tests mit schrecklicher Kraft herrschen):

HINWEIS
Genau das ist dann der Fall, wenn ein Unit-Test nicht nur ein Test ist, der die Korrektheit der Implementierung einer bestimmten Funktionalität überprüft. Das ist genau der Fall, von dem Kent Beck wiederholt gesprochen hat, als er die Rechenschaftspflicht beschrieben hat; Wenn Sie diesen Test lesen, können Sie verstehen, woran der Entwickler der Validierungsmethode gedacht hat, sein Wissen „wiederverwenden“ und Fehler in seiner Argumentation und damit wahrscheinlich im Implementierungscode finden. Es ist nicht nur eine Testsuite – es ist ein wichtiger Teil der Spezifikation für diese Methode!

Private static void PreviewTextInputForDouble(object sender, TextCompositionEventArgs e) ( // e.Text enthält nur neuen Text, daher ist der aktuelle // Zustand der TextBox unverzichtbar var textBox = (TextBox)sender; string fullText; // Wenn die TextBox enthält ausgewählten Text, dann ersetzen Sie ihn durch e.Text if (textBox.SelectionLength > 0) ( fullText = textBox.Text.Replace(textBox.SelectedText, e.Text); ) else ( // Andernfalls müssen wir neuen Text einfügen bei die Cursorposition fullText = textBox.Text.Insert(textBox.CaretIndex, e.Text); ) // Jetzt den empfangenen Text validieren bool isTextValid = TextBoxDoubleValidator.IsValid(fullText); // Und das TextChanged-Ereignis verhindern, wenn der Text nicht ist gültig e.Handled = !isTextValid; )

Die Testmethode kehrt zurück Stimmt wenn der Parameter Text gültig ist, was bedeutet, dass der entsprechende Text eingetippt werden kann Textfeld mit angehängter Eigenschaft IsDouble. Achten Sie auf ein paar Dinge: (1) die Verwendung des Attributs SetKultur, der das gewünschte Gebietsschema festlegt, und (2) einige Eingabewerte wie „-.“, die keine gültigen Werte für den Typ sind Doppelt.

Eine explizite Locale-Einstellung ist erforderlich, damit Tests für Entwickler mit anderen persönlichen Einstellungen nicht fehlschlagen, da im russischen Locale das Symbol ',' (Komma) als Trennzeichen verwendet wird und im amerikanischen - '.' (Punkt ). Seltsamer Text wie „-“. ist richtig, da der Benutzer die Eingabe vervollständigen muss, wenn er die Zeichenfolge „-.1“ eingeben möchte, was der richtige Wert für ist Doppelt. (Interessanterweise wird StackOverflow sehr oft empfohlen, einfach Double.TryParse zu verwenden, um dieses Problem zu lösen, was in einigen Fällen offensichtlich nicht funktioniert).

HINWEIS
Ich möchte den Artikel nicht mit Details zur Methodenimplementierung überladen Ist gültig, ich möchte nur die Verwendung der ThreadLocal-Methode im Hauptteil von this erwähnen , mit dem Sie abrufen und zwischenspeichern können DoubleSeparator lokal für jeden Thread. Vollständige Implementierung der Methode TextBoxDoubleValidator.IsValid finden Sie weitere Informationen zu ThreadLokal Sie können den Artikel Working with Threads von Joe Albahari lesen. Teil 3.

Alternativlösungen

Neben der Erfassung von Ereignissen VorschauTextEingabe und Einfügen von Text aus der Zwischenablage gibt es andere Lösungen. So bin ich beispielsweise auf einen Versuch gestoßen, das gleiche Problem zu lösen, indem ich das Ereignis abgefangen habe PreviewKeyDown mit Filterung aller Tonarten außer digital. Allerdings ist diese Lösung komplizierter, weil man sich noch mit dem „summary“-Zustand der TextBox herumschlagen muss, und rein theoretisch kann das Trennzeichen der Integer- und Bruchteile nicht ein Zeichen sein, sondern der ganze String (NumberFormatInfo.NumberDecimalSeparator kehrt zurück Schnur, und nicht verkohlen).
Es gibt eine weitere Option in der Veranstaltung Taste nach unten vorherigen Zustand speichern TextBox.Text, und in der Veranstaltung Textgeändert geben Sie den alten Wert zurück, wenn der neue Wert nicht passt. Aber diese Lösung sieht unnatürlich aus, und es wird nicht so einfach sein, sie mit angehängten Eigenschaften zu implementieren.

Fazit

Als wir das letzte Mal mit Kollegen über das Fehlen nützlicher und sehr typischer Features in WPF diskutiert haben, kamen wir zu dem Schluss, dass es dafür eine Erklärung gibt, und das hat auch eine positive Seite. Die Erklärung läuft darauf hinaus, dass es kein Entkommen aus dem Gesetz der undichten Abstraktionen gibt und WPF als sehr komplexe „Abstraktion“ wie ein Sieb fließt. Die nützliche Seite ist, dass das Fehlen einiger nützlicher Funktionen uns manchmal nachdenklich macht (!) Und vergessen Sie nicht, dass wir Programmierer sind, keine Copy-Paste-Handwerker.

Ich möchte Sie daran erinnern, dass die vollständige Implementierung der Klassen der oben genannten Klassen, Beispiele für ihre Verwendung und Einheitentests auf github zu finden sind.

Tags: Tags hinzufügen

In diesem Handbuch betrachten wir nur die Eingabe von Zahlen des Benutzers. BEI Microsoft Visual Studio Es gibt eine Kontrolle " MaskedTextBox“, mit seiner anpassbaren Eingabemaske, aber wir gehen davon aus, dass uns heute nur interessiert« Textfeld».
Um diese Aufgabe zu implementieren, verwenden wir das Ereignis " Tastendruck“, das auftritt, wenn eine Taste gedrückt wird, während das Steuerelement den Fokus hat. Erstellen Sie ein Projekt Fenster bilden in Microsoft Visual Studio und fügen Sie dem Hauptformular ein Steuerelement hinzu Textfeld". Wählen Sie diese Komponente aus und klicken Sie mit der rechten Maustaste darauf, wählen Sie aus dem angezeigten Kontextmenü den Punkt " EigenschaftenTastendrucktextBox1_KeyPress", Entwicklungen " Tastendruck».
Bei jeder Veranstaltung Tastendruck» übergebenes Objekt « KeyPressEventArgs". Dieses Objekt enthält die Eigenschaft " Schlüsselzeichen“ steht für das Zeichen der gedrückten Taste. Wenn Sie beispielsweise die Tasten UMSCHALT + D drücken, gibt diese Eigenschaft den Großbuchstaben D und seinen Code 68 zurück. Es gibt auch eine Eigenschaft " abgewickelt', die verwendet wird, um festzustellen, ob das Ereignis behandelt wurde. Durch Setzen des Wertes " abgewickelt" in " Stimmt", wird das Eingabeereignis nicht abgesetzt Betriebssystem für die Standardverarbeitung.
Sehen wir uns einige Beispiele für das Erstellen von Dateneingabebeschränkungen in einem Textfeld an.
Beispiel 1:
textBox1_KeyPress".

if ((e.KeyChar<= 47 || e.KeyChar >= 58) && e.KeyChar != 8) e.Handled = true; Dieses Beispiel enthält zusammengesetzte Bedingungen mit logischen Operatoren wie z &&(und), || (oder), ! (nicht) und überprüft den Dezimalcode des eingegebenen Zeichens gemäß zwei Bedingungen:

  • "e.KeyChar != 8" - Wenn die "Backspace"-Taste gedrückt wurde, dann Zeichenlöschung zulassen.
  • "(e.KeyChar<= 47 || e.KeyChar >= 58 )" - Wenn das eingegebene Zeichen einen ASCII-Code kleiner oder gleich 47 und größer oder gleich 58 hat, dann ist die Eingabe verboten.
Drunter ist ASCII-Codetabelle, in der Zeichen rot hervorgehoben sind, deren Eingabe verboten ist, und grün, deren Eingabe erlaubt ist.

Beispiel 2:
Fügen Sie die folgende Auflistung zu " textBox1_KeyPress».
if (!Char.IsDigit(e.KeyChar) && e.KeyChar != Convert.ToChar(8)) ( e.Handled = true; ) Dieses Beispiel verwendet auch logische Operatoren wie z &&(und), ! (nicht) und der Dezimalcode des eingegebenen Zeichens wird gemäß zwei Bedingungen überprüft. Die Methode dient der Überprüfung Char.IsDigit", was zurückgibt " Stimmt"" wenn das eingegebene Unicode-Zeichen eine Dezimalziffer ist und " FALSCH", wenn nicht. Es gibt auch eine Überprüfung für das Drücken der Taste " Rücktaste».
Beispiel 3:
if (!(Char.IsDigit(e.KeyChar)) && !((e.KeyChar == ".") && (((TextBox)sender).Text.IndexOf(".") == -1) && ( ((TextBox)sender).Text.Length != 0))) ( if (e.KeyChar != (char)Keys.Back) ( e.Handled = true; ) ) In diesem Beispiel, wie auch im vorigen, wird der Code des eingegebenen Zeichens mit dem " Char.IsDigit“, aber es gibt eine zusätzliche Bedingung, die die Eingabe von einem erlaubt Dezimaltrennzeichen. Dazu wird die Methode verwendet Text.IndexOf". Diese Methode sucht unter Verwendung der aktuellen Kultur wortweise nach einem Punkt. Die Suche beginnt in diesem Fall an der ersten Zeichenposition (der aktuellen Zeile) und wird bis zur letzten Zeichenposition fortgesetzt. Wenn das angegebene Symbol nicht gefunden wurde, gibt die Methode den Wert " -1 ". Wenn das Symbol gefunden wurde, gibt das Verfahren eine Dezimalzahl zurück, die die Position des gegebenen Symbols angibt, und verbietet die Verarbeitung der Eingabe des Symbols.

Dezimaltrennzeichen- das Zeichen, das verwendet wird, um die ganzen und gebrochenen Teile einer reellen Zahl in Form eines Dezimalbruchs im Dezimalsystem zu trennen. Für Brüche in anderen Zahlensystemen kann der Begriff Trennzeichen der ganzen und gebrochenen Teile einer Zahl verwendet werden. Manchmal werden auch die Begriffe Dezimalpunkt und Dezimalpunkt verwendet. (http://ru.wikipedia.org).
Weitere Informationen zur Methode Text.IndexOf» erhalten Sie unter: http://msdn.microsoft.com .

Beispiel 4:
Fügen Sie die folgende Auflistung zu " textBox1_KeyPress».

if (!System.Text.RegularExpressions.Regex.Match(e.KeyChar.ToString(), @"").Success) ( e.Handled = true; ) Um die eingegebenen Zeichen zu überprüfen, wird in diesem Beispiel die Methode " Regex-Übereinstimmungen". Diese Methode durchsucht die Eingabezeichenfolge nach allen Vorkommen des angegebenen regulären Ausdrucks. Ein regulärer Ausdruck ist ein Zeichenmuster, das eine Folge von Zeichen beliebiger Länge darstellt. Sie können einen beliebigen regulären Ausdruck angeben, zum Beispiel nur Zeichen zulassen " ' oder Eingabe des Dezimaltrennzeichens zulassen ' ,|.| ».
Beispiel 5:
Fügen Sie die folgende Auflistung zu " textBox1_KeyPress».

if (!System.Text.RegularExpressions.Regex.IsMatch(e.KeyChar.ToString(),@"\d+")) e.Handled = true; Dieses Beispiel verwendet auch den angegebenen regulären Ausdruck, um die Validierung des eingegebenen Zeichens zu implementieren. Der reguläre Ausdruck verwendet das " + “, was bedeutet, dass ein oder mehrere Zeichen des gleichen Typs gefunden werden sollen. Zum Beispiel, \d+ entspricht den Zahlen "1", "11", "1234" usw. Wenn Sie sich nicht sicher sind, welche Nummern auf die Nummer folgen? Sie können festlegen, dass entweder eine beliebige Anzahl von Ziffern oder keine Ziffern zulässig sind. Dafür ist das Symbol „ * ».
Beispiel 6:
Um dieses Beispiel zu implementieren, müssen Sie das Ereignis " Taste nach unten", das Steuerelement " textBox1". Gehen Sie zum Hauptformularkonstruktor und wählen Sie die Komponente " textBox1". Klicken Sie mit der rechten Maustaste auf dieses Steuerelement, wählen Sie aus dem angezeigten Kontextmenü den Eintrag " Eigenschaften". Gehen Sie in dem sich öffnenden Fenster zu Komponentenereignisse (das Blitzsymbol oben im Fenster) und suchen Sie das Ereignis " Taste nach unten“, doppelklicken Sie auf dieses Ereignis. Nachdem Sie alle Schritte abgeschlossen haben, gelangen Sie zur automatisch generierten Methode " textBox1_KeyDown", Entwicklungen " Taste nach unten". Dieses Ereignis tritt jedes Mal auf, wenn eine Taste gedrückt wird, während das Steuerelement den Fokus hat.

Tastatureingabeereignisse

Wenn der Benutzer eine Taste drückt, wird eine Reihe von Ereignissen ausgelöst. Die Tabelle listet diese Ereignisse in der Reihenfolge ihres Auftretens auf:

Chronologie des Auftretens von Ereignissen
Name Routing-Typ Beschreibung
PreviewKeyDown Tunnelbau Tritt auf, wenn eine Taste gedrückt wird.
Taste nach unten Blase verbreitet Dasselbe
VorschauTextEingabe Tunnelbau Tritt auf, wenn ein Tastendruck abgeschlossen ist und das Element eine Texteingabe empfängt. Dieses Ereignis tritt nicht bei Tasten auf, die keine Zeichen "drucken" (z. B. tritt es nicht auf, wenn die Tasten gedrückt werden , , , Cursortasten, Funktionstasten usw.)
Text Eingabe Blase verbreitet Dasselbe
PreviewKeyUp Tunnelbau Tritt ein, wenn eine Taste losgelassen wird
Taste auf Blase verbreitet Dasselbe

Der Umgang mit Tastaturereignissen ist keineswegs so einfach, wie es scheinen mag. Einige Steuerelemente können einige dieser Ereignisse blockieren, um ihre eigene Tastaturbehandlung durchzuführen. Das bemerkenswerteste Beispiel ist das TextBox-Element, das das TextInput-Ereignis sowie das KeyDown-Ereignis für das Drücken bestimmter Tasten, z. B. Cursortasten, blockiert. In solchen Fällen können Sie normalerweise immer noch getunnelte Ereignisse verwenden (PreviewTextInput und PreviewKeyDown).

Das TextBox-Element fügt ein neues Ereignis hinzu, TextChanged. Dieses Ereignis wird sofort ausgelöst, nachdem ein Tastendruck den Text im Textfeld geändert hat. Zu diesem Zeitpunkt ist der neue Text jedoch bereits im Textfeld sichtbar, sodass es zu spät ist, den unerwünschten Tastendruck rückgängig zu machen.

Handhabung von Tastenanschlägen

Das Verständnis, wie Tastaturereignisse funktionieren und verwendet werden, lässt sich am besten anhand eines Beispiels bewerkstelligen. Nachfolgend finden Sie ein Beispielprogramm, das alle möglichen Tastenanschläge überwacht und protokolliert, während ein Textfeld den Fokus hat. In diesem Fall wird das Ergebnis der Eingabe eines großen S angezeigt.

Dieses Beispiel zeigt einen wichtigen Punkt. Die Ereignisse PreviewKeyDown und KeyDown werden jedes Mal ausgelöst, wenn eine Taste gedrückt wird. Das TextInput-Ereignis wird jedoch nur ausgelöst, wenn ein Zeichen in das Element "eingegeben" wurde. Tatsächlich kann dies bedeuten, viele Tasten zu drücken. Im Beispiel müssen Sie zwei Tasten drücken, um zu gelangen Großbuchstabe S: Schlüssel zuerst , und dann der Schlüssel . Dies führt zu zwei KeyDown- und KeyUp-Ereignissen, aber nur zu einem TextInput-Ereignis.

Wiederholtes Drücken von Zeichen ignorieren

Öffentliche partielle Klasse MainWindow: Window ( public MainWindow() ( InitializeComponent(); ) private void Clear_Click(object sender, RoutedEventArgs e) ( lbxEvents.Items.Clear(); txtContent.Clear(); i = 0; ) protected int i = 0; private void KeyEvents(object sender, KeyEventArgs e) ( if ((bool)chkIgnoreRepeat.IsChecked && e.IsRepeat) return; i++; string s = "Event" + i + ": " + e.RoutedEvent + " Key : " + e.Key; lbxEvents.Items.Add(s); ) private void TextInputEvent(object sender, TextCompositionEventArgs e) ( i++; string s = "Event" + i + ": " + e.RoutedEvent + " Key: " + e.Text; lbxEvents.Items.Add(s); ) )

Die Ereignisse PreviewKeyDown, KeyDown, PreviewKey und KeyUp übergeben jeweils dieselben Informationen an das KeyEventArgs-Objekt. Der wichtigste Teil ist die Key-Eigenschaft, die einen Wert aus der System.Windows.Input.Key-Enumeration zurückgibt und die gedrückte oder losgelassene Taste identifiziert.

Der Key-Wert berücksichtigt nicht den Zustand einer anderen Taste, z. B. ob die Taste gedrückt wurde zum Zeitpunkt des Pressens ; In beiden Fällen erhalten Sie denselben Schlüsselwert (Key.S).

Hier gibt es eine Schwierigkeit. Je nachdem, wie Ihre Tastatur in Windows eingerichtet ist, führt das Halten einer Taste dazu, dass die Taste nach kurzer Zeit erneut gedrückt wird. Zum Beispiel das Drücken einer Taste bewirkt, dass eine Reihe von S-Zeichen in das Textfeld eingegeben wird, ebenso wie das Drücken der Taste führt zu wiederholten Klicks und einer Reihe von KeyDown-Ereignissen. In einem realen Beispiel beim Drücken einer Kombination Das Textfeld generiert eine Reihe von KeyDown-Ereignissen für die Taste , dann das KeyDown-Ereignis für die Taste , das TextInput-Ereignis (oder das TextChanged-Ereignis, falls Textfeld) und dann das KeyUp-Ereignis für die Tasten und . Wenn Sie Tastenanschläge ignorieren möchten , können Sie mithilfe der KeyEventArgs.IsRepeat-Eigenschaft überprüfen, ob das Drücken das Ergebnis eines Tastendrucks ist.

Die Ereignisse PreviewKeyDown, KeyDown, PreviewKey und KeyUp eignen sich besser zum Schreiben von Low-Level-Code zum Verarbeiten von Tastatureingaben (die selten benötigt werden, außer in Benutzersteuerelementen) und zum Verarbeiten von speziellen Tastendrücken (z. B. Funktionstasten).

Auf das KeyDown-Ereignis folgt das PreviewTextInput-Ereignis. (Das TextInput-Ereignis wird nicht ausgelöst, da es von TextBox blockiert wird.) Zu diesem Zeitpunkt wird der Text noch nicht im Steuerelement angezeigt.

Das TextInput-Ereignis stellt Objektcode bereit TextCompositionEventArgs. Dieses Objekt enthält eine Text-Eigenschaft, die den gerenderten Text zur Übergabe an das Steuerelement bereitstellt.

Idealerweise könnte das PreviewTextInput-Ereignis verwendet werden, um eine Validierung für Steuerelemente wie die TextBox durchzuführen. Wenn Sie beispielsweise ein Textfeld erstellen, das nur Zahlen akzeptiert, können Sie überprüfen, ob der aktuelle Tastendruck einen Buchstaben eingegeben hat, und das Flag Behandelt setzen, wenn dies der Fall ist. Leider wird das PreviewTextIlnput-Ereignis für einige Schlüssel, die behandelt werden müssen, nicht generiert. Wenn Sie beispielsweise in einem Textfeld die Leertaste drücken, wird das PreviewTextInput-Ereignis vollständig übersprungen. Das bedeutet, dass Sie auch das PreviewKeyDown-Ereignis behandeln müssen.

Leider ist es schwierig, eine robuste Datenvalidierungslogik im PreviewKeyDown-Ereignishandler zu implementieren, da nur der Schlüsselwert ist verfügbar, und dies ist eine Information auf zu niedriger Ebene. Beispielsweise unterscheidet die Key-Enumeration zwischen Tasten auf dem Ziffernblock (ein Block nur zur Eingabe von Zahlen) und einer normalen Tastatur. Das bedeutet, je nachdem, wo die Taste 9 gedrückt wird, erhalten Sie entweder Key.D9 oder Key.NumPad9. Das Überprüfen aller gültigen Werte ist zumindest sehr mühsam.

Ein Ausweg ist die Verwendung der Klasse KeyConverter, wodurch Sie den Schlüsselwert in eine nützlichere Zeichenfolge konvertieren können. Zum Beispiel ein Funktionsaufruf KeyConverter.ConvertToString() mit einem der Key.D9- und Key.NumPad9-Werte gibt das Zeichenfolgenergebnis „9“ zurück. Der Aufruf der Key.ToString()-Konvertierung ergibt einen weniger nützlichen Enum-Namen (entweder „D9“ oder „NumPad9“):

KeyConverter-Konverter = new KeyConverter(); string key = converter.ConvertToString(e.Key);

Allerdings ist die Verwendung von KeyConverter auch nicht sehr komfortabel, da Sie bei denjenigen Tastenanschlägen, die keine Texteingabe bewirken, mit langen Zeilen (z. B. "Backspace") umgehen müssen.

Die geeignetste Option ist die Behandlung des PreviewTextInput-Ereignisses (bei dem der größte Teil der Überprüfung erfolgt) in Verbindung mit dem PreviewKeyDown-Ereignis für Tastendrücke, die kein PreviewTextInput-Ereignis für das Textfeld (z. B. die Leertaste) generieren.



Unterstützen Sie das Projekt - teilen Sie den Link, danke!
Lesen Sie auch
Spielregeln für Hahnenkämpfe Spielregeln für Hahnenkämpfe Mod für Minecraft 1.7 10 Uhr Rezepte.  Rezepte zum Herstellen von Gegenständen in Minecraft.  Waffen in Minecraft Mod für Minecraft 1.7 10 Uhr Rezepte. Rezepte zum Herstellen von Gegenständen in Minecraft. Waffen in Minecraft Schilling und Pfund Sterling - der Ursprung der Wörter Schilling und Pfund Sterling - der Ursprung der Wörter