ReadOnly TextBox mit Caret

  • WPF

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von Plexian.

    ReadOnly TextBox mit Caret

    Hey Community,

    ich hab leider noch ein Problem (3 Themen in 3 Tagen, yippie) :
    Ich möchte, dass der User die Möglichkeit hat, einen internen String mit Tastendrücken zu befüllen. Da ich nur bestimmte Keys erlauben wollte, ist meine bisherige Lösung über die Window.InputBindings und dann per Command einer Property hinzufügen, die wiederum an einen TextBlock gebunden ist zum anzeigen - funktioniert, alles gut.
    Das Ganze setzt aber voraus, dass neue Eingaben immer am Ende hinzukommen, ist okay, aber suboptimal. Was ich also brauche, ist eine Möglichkeit einen Caret zu haben, der hinundher bewegbar ist, mit Pfeiltasten denke ich mal.
    Zwei Ideen hatte ich:
    1) TextBlock durch TextBox ersetzen, Design aber wie bei TextBlock (transparent, no border, textwrapping) und IsReadOnly. Dann ist aber der Cursor trotzdem nicht da. Mach ich die Box nicht ReadOnly, hab ich zwar den Cursor, aber kann ja eingeben was ich will, dann sind die KeyBindings useless. Also im CodeBehind im KeyDown-Event einfach e.Handled = true; dann ist zwar der/die/das Caret da, aber keine Eingabe mehr möglich, selbst mit den KeyBindings des Windows (verwundert mich iwie, aber ist so, es sei denn ihr habt da ne Idee?).
    2) Auch einfach TextBox nutzen, und dann im CodeBehind nur bei den erlaubten Keys e.Handled auf false lassen, aber ich weiß nicht wie WPF-konform das ist.

    Ich hoffe, das Problem wurde klar.

    Danke im Voraus,
    Plexian

    P.S.: Braucht mir keinen Award für wunderschönes Denglish zu verleihen ;)
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais

    Plexian schrieb:

    Auch einfach TextBox nutzen, und dann im CodeBehind nur bei den erlaubten Keys e.Handled auf false lassen, aber ich weiß nicht wie WPF-konform das ist.


    Das wäre wohl mein Vorschlag.

    Grüße
    "Life isn't about winning the race. Life is about finishing the race and how many people we can help finish the race." ~Marc Mero

    Nun bin ich also auch soweit: Keine VB-Fragen per PM! Es gibt hier ein Forum, verdammt!
    @Nikx gut, das präferiere ich nämlich auch, ich war mir nur nicht sicher wie sehr das WinForms-Style ist anstatt WPF.
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais
    naja, wenn was nicht anders geht, ist in wpf auch das CodeBehind ok. Codebehind zählt zum View, also wie eine Textbox sich verhält, kann man auch im View belassen.
    Ist halt die Frage, wie kompliziert die Tasten-Unterdrücker-Logik ist, und v.a. ob die nicht eigentlich auch vom Viewmodel abhängt.
    Also ganz 100%ig wäre ein Behavior zu schreiben, aber ich find, man soll auch danach gucken, welcher Aufwand sich lohnt.
    Hab jz ein wenig rumgebastelt, und folgendes ist erstmal bei raus gekommen (KeyBindings hab ich auskommentiert):

    C#-Quellcode

    1. private void ExpressionBoxOnKeyDown(object sender, KeyEventArgs e)
    2. {
    3. e.Handled = true;
    4. var nums = new[] {Key.D0, Key.D1, Key.D2, Key.D3, Key.D4, Key.D5, Key.D6, Key.D7, Key.D8, Key.D9};
    5. var numpad = new[] { Key.NumPad0, Key.NumPad1, Key.NumPad2, Key.NumPad3, Key.NumPad4, Key.NumPad5, Key.NumPad6, Key.NumPad7, Key.NumPad8, Key.NumPad9 };
    6. var chars = new[] {Key.OemPlus, Key.OemMinus, Key.Oem5, Key.OemComma, Key.OemPeriod};
    7. var specials = new[] {Key.Space, Key.Back};
    8. if (new[] {nums, numpad, chars, specials}.SelectMany(key => key).Contains(e.Key))
    9. e.Handled = false;
    10. var shifted = new[] { Key.OemPlus, Key.D8, Key.D9, Key.D5, Key.D7, Key.E };
    11. if ((Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) && shifted.Contains(e.Key))
    12. e.Handled = false;
    13. }

    Das funktioniert auch soweit gar nicht so so schlecht, bis auf ein paar Dinge:
    1) Die Enter-Taste, welche eig noch von den Window.InputBindings aufgefangen werden soll, geht nicht mehr
    2) Genauso die Escape-Taste (ClearAll), welche aber wieder geht, wenn ich das KeyBinding in die TextBox.InputBindings verschiebe
    3) Da man immer schreiben können soll, muss die TB durchgehend (!) fokussiert sein, und nicht mal das hilft: ExpressionBox.LostFocus += (sender, args) => FocusManager.SetFocusedElement(outerGrid, ExpressionBox);
    4. Beim Drücken von dem Caret (Oem5, ^ das hier), hört die TB komplett auf Eingaben entgegenzunehmen (wartet wahrscheinlich auf sowas wie ein a um ein â draus zu machen)

    --> Langsam stelle ich mir die Frage, ob ich nicht beim alten TextBlock bleibe und den Cursor einfach selbst animiere :D
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais
    zu deiner Eingangsfrage, ob das wpf-konform sei, tätich sagen ja.
    Da ist weder was festverdrahtet, was eigentlich Daten wäre, noch wird in ein Viewmodel gegrabscht, sondern lediglich das daten-unabhängige Verhalten eines Controls modifiziert.
    Solch ist im Codebehind gut untergebracht, und wenn es wiederverwendbar werden soll, kann man auch ein Behavior davon stricken.

    Zu dem andern weiß ich nichts - ich hab nicht verstanden, was das Verhalten der TB sein soll, wenn fertig ist.
    @ErfinderDesRades Prinzipiell möchte ich eine TextBox im TextBlock-Design (hab ich), die nur bestimmte Eingaben zulässt.
    Wichtig dabei ist, dass diese dauernd fokussiert ist (sprich Tastendrücke immer bei der TextBox ankommen), aber trotzdem bestimmte Tasten mit Commands verknüpft sind. Das heißt, ich möchte u.A. 0-9 in der TextBox dann sehen, dann aber das die Enter-Taste einen Command ausführt, die Escape-Taste die TextBox leert. Sowas.
    Deswegen meine Eingangsidee, einfach erlaubten Tasten mit KeyBindings verknüpfen, und einige fügen dann halt ein Zeichen zum ehemaligen TextBlock hinzu. Langte aber nicht, ich brauche die Möglichkeit den Cursor oder Caret (ich weiß nicht richtig wie das blinkende Ding heißt) zu verschieben.

    Ich hoffe das ist klarer geworden, und somit auch meine Probleme, die noch bestehen:

    Plexian schrieb:

    Das funktioniert auch soweit gar nicht so so schlecht, bis auf ein paar Dinge:
    1) Die Enter-Taste, welche eig noch von den Window.InputBindings aufgefangen werden soll, geht nicht mehr
    2) Genauso die Escape-Taste (ClearAll), welche aber wieder geht, wenn ich das KeyBinding in die TextBox.InputBindings verschiebe
    3) Da man immer schreiben können soll, muss die TB durchgehend (!) fokussiert sein, und nicht mal das hilft: ExpressionBox.LostFocus += (sender, args) => FocusManager.SetFocusedElement(outerGrid, ExpressionBox);
    4. Beim Drücken von dem Caret (Oem5, ^ das hier), hört die TB komplett auf Eingaben entgegenzunehmen (wartet wahrscheinlich auf sowas wie ein a um ein â draus zu machen)
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais
    ich weiß nicht, was "immer den Focus haben" für dich bedeutet. Normalerweise hat ein Control den Focus, wenn man drauf klickt, und wenn man woanners hinklickt ist der Focus woanners, und das ist auch gut so.
    Willst du den Focus in der Textbox festnageln - warum?

    Vlt. erzählst du auch mal, was das eiglich werden soll.
    @ErfinderDesRades: Ah ja, wie angedeutet, hab ich 3 Threads in den letzten Tagen eröffnet, in nem anderen Thread hatte ich das erklärt.
    Ich programmiere einen Taschenrechner, anbei mal mein momentanes View. Und das einzige Eingabefeld ist halt für den Term, und Buttons sollen den Focus auch nicht wegnehmen, es soll ähnlich funktionieren wie Standard CASIO Rechner.
    Wenn du stattdessen nen anderen Designvorschlag hast (nicht optisch, die Umsetzung), immer her damit :)
    Bilder
    • Capture.JPG

      30,08 kB, 509×314, 72 mal angesehen
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais
    ich denk, die Probleme mit reservierten Tasten (Caret, Enter) kannst du umgehen, wenn du dich auf das PreviewKeyDown-Event stürzst.
    Wie man eine immer focussierte Textbox bastelt, weiß ich leider auch nicht.

    Ich halte Taschenrechner im Computer auch für krasses Retro-Design, und bin kein Fan vons das.

    Weil ein Computer hat keine Tasche.

    Bei mir wäre ein Rechner halt eine Textbox, und zur Vereinfachung von Eingaben (Sin, Cos, etc.) gäbs noch paar Menüs zu klicksen.

    Oder ich würd mir ganz andere Konzepte ausdenken, etwa in FormelParser und ExpressionTree kann man parametrierte Ausdrücke eingeben, und dann Werte für die Parameter einsetzen, so in die Richtung würde ich einen Rechner aufblähen, da fällt mir noch einiges ein, am Ende bin ich bei Excel ;)

    Tatsächlich habe ich in meiner Zeit als Kassen-Onkel zum Aufsummieren von Bons mir ein klein Excel-Sheet gebastelt, keinen Taschenrechner.
    @ErfinderDesRades Ich denke er nutzt sicherlich einen entsprechenden Parser.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    @Trade: So isses.

    @ErfinderDesRades : Das PreviewKeyDown-Event schau ich mir an, sollte funktionieren. Ja, ein solcher Taschenrechner muss nicht allzu viel nützen, auch wenn ich schon einen gewissen Nutzen sehe - es geht darum, dass es meine Abitursprüfung wird, und der Aufwand jz schon Overhead war (hatte halt Spaß dran), wenn ich dann erst mit Parametern anfange wirds zu viel.

    ErfinderDesRades schrieb:

    Bei mir wäre ein Rechner halt eine Textbox, und zur Vereinfachung von Eingaben (Sin, Cos, etc.) gäbs noch paar Menüs zu klicksen.

    Genau das solls ja auch sein. Nur möchte ich einfach etwas Design haben und nicht umbedingt erlauben, dass jemand "kartoffelsalat" da rein schreibt.

    TL;DR; Ich probiere das PreviewKeyDown Event aus und melde mich.
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais

    Plexian schrieb:

    nicht umbedingt erlauben, dass jemand "kartoffelsalat" da rein schreibt.

    Wenn du das unterdrücken willst, dann kann man auch nicht "sin" reinschreiben.
    Das wär bischen Bedien-inkonsistent: Alles kann man eintippen, nur für sin, cos, tan braucht man die Maus.
    (aber dafür eine Lösung zu finden wird vmtl. zu aufwändig)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    ErfinderDesRades schrieb:

    Wenn du das unterdrücken willst, dann kann man auch nicht "sin" reinschreiben.

    Das dachte ich mir auch so, mag aber sein dass das als ungünstig empfunden wird.
    Ne Alternative wäre für mich, beim TextChanged ein RegEx rüberlaufen zu lassen, und bei jedem unbekannten "Wort" das erstmal kursiv zu schreiben.
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais