Jak najprościej zabezpieczyć textBox przed niewłaściwymi znakami.

0

Piszę aplikację, która poprzez LPT odczytuje i zapisuje dość wiekową pamięć EEPROM. Kwestia obsługi pamięci jest ogarnięta. Pozostała kwestia interfejsu użytkownika. EEPROM posiada całe 256 bitów zawartych w szesnastu szesnastobitowych rejestrach (16x16). Dla każdego rejestru są trzy pola tekstowe przedstawiające jego zawartość w systemie dwójkowym, szesnastkowym i dziesiętnym. Przy wpisywaniu danych w pole wartości binarnych, lub szesnastkowych, lub dziesiętnych w pozostałych polach wyświetlane są odpowiednio przekonwertowane wartości. W jaki najprostszy sposób wykonać weryfikację wprowadzanych wartości dla poszczególnych pól tekstowych? Czy da się to zrobić tylko na jednym zdarzeniu np. textBox.TextChanged, textBox.keyUp? Kopiowanie i wklejanie do pól tekstowych mam zablokowane. Moje rozwiązanie oparte textBox.TextChanged działa tak, że ostatnia, poprawnie wprowadzona wartość zostaje zapisana do zmiennej "lastValue". W momencie wprowadzenia niepoprawnego ciągu znaków, wartość pola tekstowego zostaje zastąpiona wartością ze zmiennej "lastValue". Problem jest w tym, że wtedy karetka jest ustawiana na początku ciągu. Strasznie jest to irytujące podczas wpisywania niepoprawnego znaku w środku, bo karetka ucieka na początek. Zdarzenie textBox.keyPress albo textBox.keyDown samo nie zadziała, bo wartość textBox.Text jest ustawiana po zakończeniu zdarzenia, więc zmiana systemu zapisu liczby następuje przy wprowadzaniu kolejnego znaku. Zdarzenia textBox.keyPress i textBox.TextChanged użyte razem działają bezbłędnie. Nie zarabiam na życie pisząc aplikacje, ale programistą nie płaci się za ilość linii kodu. W moim przypadku, dla 48 pól tekstowych, napisanie obsługi dwóch zdarzeń dla każdego z nich bynajmniej będzie wyglądać nieestetycznie.

0

Uzyj zdarzeń PreviewKeyUp/PreviewKeyDown

0

Nie wiedziałem o ich istnieniu. Wszystkie rozwiązania, które podsunęło mi Google nie uwzględniały tych zdarzeń. Już sprawdzam. Dziękuję
Edit:
W moim VS Express 2017 ma zdarzenia textBox.PreviewKeyUp

0

W Windows Forms nie masz PreviewKeyUp, jest tylko PreviewKeyDown. W WPF masz oba.

1
Bednarus3 napisał(a):

W moim przypadku, dla 48 pól tekstowych, napisanie obsługi dwóch zdarzeń dla każdego z nich bynajmniej będzie wyglądać nieestetycznie.

Można dla 48 widgetów przyporządkować jeden handler. W zdarzeniu jest wszystko, co pozwala rozwikłać zagadkę, skąd zdarzenie przyszło.

0

Problem jest w tym, że wtedy karetka jest ustawiana na początku ciągu. Strasznie jest to irytujące podczas wpisywania niepoprawnego znaku w środku, bo karetka ucieka na początek.

Zawsze chyba możesz pamiętać gdzie była i tam skoczyć :P

textBox1.Select(index, 0);

A tak ogólnie, to czy przypadkiem nie wystarczy Masked TextBox?

0
WeiXiao napisał(a):

Zawsze chyba możesz pamiętać gdzie była i tam skoczyć :P

Robiłem tak. Problem w tym, że podczas obsługi zdarzenia textBox.TextChenged następuje sprawdzenie poprawności tekstu. Jeżeli są niedozwolone znaki następuje zapisanie do textBox.Text ostatniej poprawnej wartości, co rekurencyjnie wywołuje zdarzenie textBox.TextChenged, przez co zapamiętana ostatnia pozycja karetki wynosi 0.

WeiXiao napisał(a):

A tak ogólnie, to czy przypadkiem nie wystarczy Masked TextBox?

Gdzieś w sieci widziałem Masked TextBox, ale wydaje mi się, że jestem za cienki, żeby z tego skorzystać.

AnyKtokolwiek napisał(a):

Można dla 48 widgetów przyporządkować jeden handler. W zdarzeniu jest wszystko, co pozwala rozwikłać zagadkę, skąd zdarzenie przyszło.

Genialne. Milion linii kodu zastąpiły dwie krótkie metody wywoływane dla wszystkich pól tekstowych w których wystąpiły zdarzenia textBox.KeyPress (obsługa niepożądanych znaków) i textBox.TextChenged (obsługa konwersji). Zrodziło się pytanie w jaki sposób wstawić przekonwertowane wartości do pól tekstowych odpowiednich dla tego, w którym była wprowadzana wartość. Mi do głowy przychodzi tylko instrukcja "switch", a w niej 48 przypadków. Czy da się to zrobić jakoś ładniej?

edit:
Wykorzystałem metodę Find do wstawienia wyniku w dwóch pozostałych polach tekstowych.

0

Jeszcze jedno pytanie. Czy da się jednym wyrażeniem regularnym usunąć niechciane zera znajdujące się na początku ciągu, w taki sposób, że jak będą same zera to zostawiamy tylko jedno?
Na przykład:
0000000000000000 zamieniamy na 0
000011111111111111 zamieniamy na 11111111111111
0000001001001000 zamieniamy na 1001001000
Edit:
W sumie rozwiązałem problem w poniższy sposób:
s = int.Parse(s).ToString();
Jak z wydajnością takiego rozwiązania?

0

Mógłbyś też użyć TrimStart('0') w celu usunięcia wszystkich zer na początku. W przypadku "00" to usunie wszystko, więc musiałbyś obsłużyć taki przypadek. Sensu nieco więcej niż z parsowaniem do inta, chociażby dlatego, że int.Parse nie zadziała dla podanych przez Ciebie przykładów.

0

Parsowanie do integer, a potem do string działa zgodnie z założeniem. Tylko nie wydaje mi się, że jest to ładne rozwiązanie. Zdarza mi się pisać program średnio raz w roku, który mieści się w około 500 liniach kodu, wiec wydajność i poprawność pisania może zejść na drugi plan. Ma działać i tyle. Ale i tak pytam się z ciekawości, bo jak coś robić to dobrze.

0
Bednarus3 napisał(a):

EEPROM posiada całe 256 bitów zawartych w szesnastu szesnastobitowych rejestrach (16x16).

Nie korzystam z więcej niż 16 bitów. Tam podałem zły przykład.

1 użytkowników online, w tym zalogowanych: 0, gości: 1