RichTextBox SelectionLength zero when Selecting outside Text Property - winforms

I'm trying to wrap my head around a behaviour in WinForms RichTextBox.
When you are using the RichTextBox and select the right end of the RichTextBox it is possible by holding shift and pushing right to select an additional character to the right.
What really boggles my mind is that the SelectionLength property of the RichTextBox is 0.
If you look at it it visually it appears you have a selection of 1 character length that starts from the end of your current Text. if you look at the curSelStart and curSelEnd properties curSelStart starts from the end of your Text property and curSelEnd one character beyond it.
We are working with our own subclass of a Winforms RichTextBox that has all manners of special behaviour implemented and among them we have an assumption that if you press backspace with a SelectionLength of 0 you will erase a character. In this case this assumption is no longer true as pressing backspace will just erase your current Selection.
Any ideas as to why it behaves this way? Any way around it?

This behaviour started giving us trouble when we started using our custom RichTextBox control with MultiLine enabled. Thus this got upgraded from an odd behavour I've observed to a bug I had to solve.
it seems to be a quirk in how RichTextBox handles linebreaks. at the end of each line there will always be a '\n' char. That is the mystery character I described in my question above. If you attempt to remove it it will be promptly readded.
With this knowlegde I could make a check if property SelectedText ends with a '\n' char and if the new text I inserted didn't contain a '\n' I would be sure that I needed to add an additional char to my offset my custom control required.
I can't believe that I didn't notice the '\n' earlier. Oh well.. The problem is resolved now.

Related

Why are there strange backspace characters in my WPF datagrid?

Our software uses the DataGrid throughout its user interface for displaying editable lists. While editing some metadata, I wanted to remove the text in a particular column for many rows. This is pretty quick if you get into the rhythm of F2-Backspace-Enter, F2-Backspace-Enter, F2-Backspace-Enter….
Things don’t go quite so well if you miss the F2 part of the pattern and just press Backspace-Enter on a cell. The WPF DataGrid will actually replace the contents of the cell with the backspace character. Depending on how you look at your string, this might show up as 0×08, , \u0008, or \b.
What on earth?
This CodePlex post confirms a bug in the DataGrid and includes some workarounds. On our end, the current fix is simply to ignore strings that have a backspace character in them. This way they don’t end up in the XML, which is good because in XML 1.0 the backspace is an illegal character.
See also this Microsoft Connect issue.

Custom Undo/Redo in WPF TextBox with proper caret-movement

I have implemented a custom Undo/Redo stack and Im trying to get it to work with the WPF TextBox.
I have turned off the built in Undo-mechanism and hooked up my custom Undo on Ctrl+Z. Everything works fine accept that the caret in the TextBox is always being moved to index 0 on every undo/redo. The question is how to solve this?
I have tried having a custom behaviour on the TextBox which listens to TextChanged and is localizing the last change in the text-string. But this only works unless you start typing the same letter several times in a row. The my method breaks down.
What I ideally want is some kind of behaviour that only makes actual changes to the TextBox.Text-property. As it is now it is updated completely for every Undo, even if its only the last entered letter that is removed. This is of course no suprise since it listens to the Text-property on my PresentationModel which is triggering PropertyChanged on Undo.
But wouldnt it be great if there was some more fine-detailed way of telling exactly what had changed with the property-value, that only one or a couple of letters where inserted/removed in the string value. Then the TextBox could change only that without having to refresh its entire Text-value. Is there any such way of telling the TextBox this allready or could it be possible to make a custom TextBox that behaved in this way? Then it would be possible to pinpoint the exact location for the new caret without having it go straight back to 0 for every propertychange-update!

In WPF how can I duplicate the old WinForms OnKeyPressed functionality?

We have a WPF application where we need to detect if the user is typing something that can appear in a textbox. WinForms used to have a nice OnKeyPressed override that differed from OnKeyDown in that it was only called when a printable character was typed (e.g. it differentiated between 'A' and 'a' but not between the '1' on the top row vs. the numeric keypad. It also ignored keys like 'Shift', etc.) We need to duplicate that functionality in WPF.
Now I know I can override OnKeyDown and inspect the keycode, but that means manually testing for every possible key that would result in something appearing in a textbox. That seems to be the consensus from the other similar SO questions that I've found, but I just can't believe something so basic would be left out of the API.
Asides from a monster if-tree, one 'hacky' solution is to use an in-memory textbox, pass the keycode to it, then inspect if the text has a length. But I'm getting nauseous even typing that as a possible solution! UGH!! I feel dirty!
SO... what's the easiest way to tell if a user pressed a key or keys that will result in a printable character?
TIA,
Mark
Actually, I think I just found it so I'm posting the answers for others. You don't use any 'Key' events at all. WPF more clearly separates those out from the textual values. As such, you override the OnPreviewTextInput and/or OnTextInput functions. To get what was actually typed, check the .Text property on the event args which returns a simple string.
Done and done!
Hope this helps others! Been driving me up a wall!

How do you detect incoming text ctrl-v pasting in a winforms textbox?

I'm making my own commentbox control that inherits from a winforms textbox. One of the things it does is prevent users from entering any characters if the limit has been hit. So on the keypress event I just grab the incoming key (excepting delete and backspace) and add it on to what's in the textbox already, then check and see what the length is. If it is over, then I just set the e.Handled = true and the keypress is halted. This scheme fails me though on an incoming ctrl-v paste event. It registers as a single keychar coming in. So the paste won't come through if I'm right at the limit, but it will go over if there is one character of room left and the paste has two or more characters for instance.
I just need a way to detect that this paste is coming in, and when its coming in I need to know what the length of the string is so I can either stop it from happening or paste as much of it as possible in there.
Thanks!
This is such an idle question. You can just set the MaxLength property of the textbox and it prevents all of this. Duh.

WPF TextBox - programatically select text while preserving "selection direction"

When editing text the user is able to use the keybord shift button and direction keys to modify the selection - one position stays anchored while the other moves. By pressing left it is possible to get the movable part on the left of the anchored part.
I'm trying to dinamicaly modify the users selection in WPF's TextBox (for the purpose of the discussion, lets say I want to select the characters in pairs, eg. when pressing shift+left, 2 characters would get selected, not just one). However, when using SelectionStart/SelectionIndex/CaretIndex/Select the "movebale end" of the selection is always ends up on the far right end of the selection, rendering the shift+left combination useless.
Any way to preserve the "selection direction"?
This is not quite the answer you are looking for but it'll work. Invoke the command and do it the way WPF does it.
EditingCommands.SelectLeftByCharacter.Execute(null, textBox1);
None of those work. SelectionLength doesn't allowed to be negative, and CaretIndex is always identical to SelectionStart. This is a design bug in TB, as you cannot achieve a valid state of it even in the protected scope.
The command actually works, but you still cannot determine the selection's direction of the currently analyzed textbox. There's only one solution, which is an ugly workaround: You can write your own observer code by overriding the mouse and keyboard event handlers.
The only possibility I can think of is to set the SelectionStart and then make the SelectionLength negative.
Have you tried setting the CaretIndex property before or after setting SelectionStart/SelectionLength?

Resources