Von den Höhen der Programmstrukturierung zu den Niederungen der Programmierung zu Fuß.
Der Adler, sagte Bismarck einmal, übersieht in seinem Fluge die Hindernisse am Boden.
Wir wollen Adler sein, müssen aber zu Fuß gehen.
Es gibt immer auch technische Probleme zu lösen bei dem Dialog mit dem Anwender.
Grundsätzlich sollte man es vermeiden, daß der Anwender völlig freihändig irgendwelchen Unsinn eingeben darf. Weil diese EIngabe dann umständlich auf Fehlerhaftigkeit geprüft werden muß.
Ich persönlich liebe das auch gar nicht, von der Maus auf die Tastatur zu wechseln. Wenn man mit der Maus einmal dran ist, will man auch alle Eingaben mit der Maus machen.
Manchmal geht es nicht. Man braucht dann mit der Tastatur frei einzugebende Felder.
Die erwarten irgendwas, z. B. eine numerische Eingabe, und es muß eine Fehlerbehandlung erfolgen.
In Bezug auf die Anzahl der zu bestellenden Artikel hab ich die freie Eingabe rausgenommen (textBox) zugunsten einer comboBox, die bestimmte Stückzahlen zur Verfügung stellt, z. B. 1,2,3,4,5,10,15,20,50,100,200,500.
Der Anwender kann dann eine von den Optionen wählen, und wir wissen, wir haben kein Formatierungsproblem mit der Umwandlung des Stringwertes in ein Integer, weil die Auswahl ja vorgegeben wurde.
Leider ist es bei der comboBox so, daß der Anwender nicht nur klicken kann, sondern auch mit der Tastatur reinschreiben darf. Ziemlich unsinnig, ist aber so, insbesondere ist das unsinnig, weil dann ein Laufzeitfehler die sichere Folge ist. Nämlich eine außerhalb des Indexes oder null Exception. Das ist ja die alte Frage bei den Eingabefunktionen in Ansi-C, wie man einen buffer-Overflow erzeugt, die Scanf() Funktion ist da so ein Kandidat.
Um die comboBox an einem Laufzeitfehler zu hindern, wäre die Eigenschaft readonly=true wünschenswert, die comboBox hat die aber nicht.
Um readonly zu simulieren, gibt es allerdings eine Möglichkeit. Nämlich, bei der comboBox müssen wir die Eigenschaft dropdownstyle auf dropdownlist setzen, und haben das gewünschte Ergebnis.
Eine andere technische Frage ist, wie man eine frei einzugebende Textbox abfragt.
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
ist dafür ungeeignet, weil der Ereignishandler nicht abwartet, bis die Eingabe beendet ist, sondern schon beim ersten Zeichen in Aktion tritt.
Wir könnten uns entscheiden, das Ereignis "ENTER" zu wählen, daß der Anwender also die Eingabe mit ENTER abschließen muß.
Sobald ENTER gedrückt wurde, meldet die textBox, daß ENTER gedrückt wurde, und das Ereignis kann verarbeitet werden.
Leider ist es so, daß bei ENTER ein häßlicher Piepton ausgeworfen wird.
Wie kriegt man den weg?
Das hier ist aus dem Internet unter dem witzigen Begriff "How to Stop the 'Ding" when pressing Enter".
Antwort auf das DING, was ja im Deutschen andere Bedeutung hat, ist z. B. die hier:
private void keypressed(Object o, KeyPressEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
e.Handled = true; //this line will do the trick
}
}
That will do the trick, aber nicht so, sondern etwas anders, sonst wäre es ja auch zu einfach:
private void tbPreisnachlass_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == CBas.ENTER)
{
e.Handled = true;
pruefeEingabe(this.tbPreisnachlass);
}
}
Wobei in der statischen Klasse CBas der Wert für ENTER mit 13 hinterlegt wurde.
Sobald der Anwender also sein freies Textfeld, was eine Zahl erwartet, mit ENTER abschließt, kann die zentrale Methode diese Eingabe überprüfen.
Wir erwarten z. B. einen double (für int müßte man das ähnlich behandeln).
Dafür brauchen wir eine Funktion, die den String, ohne einen Laufzeitfehler auszulösen, überprüft und im Fehlerfall eine default-Wert zurückliefert, z. B. wenn der Anwender asdf eingegeben hat anstelle 19.23 oder 19,23, den Wert 0.0;
Wobei wir dann noch das Komma/Punkt Problem in einem Aufwasch behandeln.
Eine solche Methode findet sich in CFormat (in diesem Demo-Programm)
public static double string_to_double(string str)
{
double result=0.0;
string strkopie="";
if (str == null) return 0.0;
if (str.Length == 0) return 0.0;
try
{
foreach (char
element in str)
if (element == CBas.PUNKT) strkopie += CBas.KOMMA;
else strkopie += element;
result = Convert.ToDouble(strkopie);
}
catch
{
result = 0.0;
}
return result;
}
Strings sind da sehr zickig.
Wir prüfen erstmal auf null.
Würden wir erstmal auf str.Length() prüfen, und str wäre null, hätten wir schon einen Laufzeitfehler. Reihenfolge also nicht zufällig.
Wenn str.Length==0 so wäre, würde allerdings foreach() die Sache abfangen, nämlich gar nicht in Betrieb gehen. Das hier ist mit Gürtel und Hosenträger.
Die Methode leistet also, daß der String ohne Laufzeitfehler in einen double-Wert überführt wird, und gestattet Punkt und Komma.
Das ist wichtig, solche Methoden zu haben, weil man sonst an jeder Stelle des Codes diese Codierung einfügen müßte, Stichwort Redundanz und Fehlercode.
Der Beitrag wurde von sharky2014 bearbeitet: 12.04.2014, 21:17 Uhr