Suppose we inherit from WPF TextBox and then try to get text changes through overriding OnTextChanged.
Then we would notice when changes occurred, but the only information that we would have is:
Offset that this change occurred
Removed Length
Added Length
Can we get the accurate added text by using,
Text.Substring(Change.Offset, Change.AddedLength)
in OnTextChanged?
Text Change occurs in different conditions (such as user input, pasting text, or setting Text property in-code). Is there any possibility of conflicting changes coming into e.Changes?
Is this approach a trust way? If answer is No, Is there any other standard way(s) to get accurate changed text?
For a TextBox, this event occurs when its text changes; for a RichTextBox, this event occurs when any content or formatting changes (for example, images, table, or background color).
Can we get the accurate added text by using ... ?
Yes, you will always get accurate text in case of TextBox. You can make use of e.UndoAction to check for addition/deletion of text.
Read documentation here.
Is there any possibility of conflicting changes coming into e.Changes?
There won't be conflicting changes.
In general, the following will always be true:
The changes that occur result in the document being in a valid state.
The collection is ordered consecutively, related to where the change occurred in the control. For example, a TextChange object
that represents a change at position 2 is before a TextChange
object that represents a change at position 10.
Two TextChange objects do not represent an overlapping area. The value of Offset plus the value of AddedLength of one TextChange
object is always less than or equal to the value of Offset of the
next TextChange object in the collection. Likewise, the value of
Offset plus the value of RemovedLength of one TextChange object is
always less than or equal to the value of Offset of the next
TextChange object in the collection.
The collection reflects whatever changes occurred, even if there seems to be no net change. In the preceding example, neither the
first or fourth change results in a net change, because each simply
removed and re-added the and symbols, respectively. But
the symbols were actually removed and added, so they are included in
the collection.
More can be read here.
I made a short test program with one TextBox and one Label and I could not find the problems you describe. If I implement an TextChanged event for the TextBox like the following it works even if I paste something.The checking for null is needed because if the Textbox has an initial value the Initilialize method will trigger the change event before the label is created.
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox tbSource = (sender as TextBox);
if (lblOutput == null)
return;
lblOutput.Content = tbSource.Text;
}
Related
This is hard to explain so please look at the WPF gif below -
I have a textbox with a stringformat {0:N2} and bound to a property.
There are two problems here -
(1) When hitting the decimal key, another decimal is added.
(2) During backspace, after deleting the decimal digits - the caret doesn't jump over the decimal rather starts adding '00' to the number itself.
I did a workaround for point (1) -
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Decimal)
{
e.Handled = true;
((TextBox)sender).CaretIndex += 1;
}
}
If there is a better way to handle such things in application - please do let me know.
Now, how do I handle the second problem? The workaround Im trying to implement is - if decimal point reached, handle the key press and move the caret position. Not sure if this is a good solution and if so, how to know when I have reached the decimal point?
Comparing the caret index to the length of the textbox value just to know if it has reached the decimal point seems like overdoing it. What is the correct solution to these 2 problems?
The problem is due to when the stringformat is being applied to the value.
Which is as the value comes back from the binding Source ( the bound string property ) to the TextBox Text ( the Target ).
And it's linked to metadata of textpropety.
The Textbox TextProperty binds twoway, this is set in the metadata of that dependency property.
The default behaviour of a textbox is to copy the value to the bound source when the control loses focus.
If you use that then the n2 format is applied once the user has finished editing. They may fix up whatever they like with the zeroes and decimal point and the format only gets applied when they tab away.
By contrast, if you set UpdateSourceTrigger="PropertyChanged" in your binding then you will find it behaves weirdly. This is because the user types a letter, the whole value is transferred to the bound property which notifies the control it changed.
All sorts of weird bad things happen as the formatting is being applied.
It's possible that this is an edge case whoever built the textbox didn't consider.
Why does DataGridView raise CellValidating event upon simple navigation through arrow keys? How can I prevent it? Here is the key information about DataGridView state when it calls CellValidating:
EditMode = EditOnKeyStrokeOrF2
IsCurrentCellInEditMode = False
e.FormattedValue = [Same as the current value of the cell]
As you can see, user has not triggered any editing operation. He's just moving across the cells by pressing right-arrow key. One would not expect validation to occur at this point, right?
Note: Examining call stack shows that KeyDownevent triggers a CommitEdit call, which in turn raises OnCellValidating.
Like it or not, this is the way things are desigend to work. See MSDN on CellValidating:
Occurs when a cell loses input focus, enabling content validation.
And to make it complete MSDN on CellValidated:
Occurs after the cell has finished validating.
The most direct and readable solution is probably to put a line like this at the start of the CellValidating event:
if (!dataGridView1.IsCurrentCellDirty) return;
One reason for the designed behaviour could be the case where a user input is actually needed to create a valid cell value. Not your case, but still a conceivable requirement.
I have a c# program set up that is supposed to accept a quantity input if a checkbox is checked. It then multiplies the quantity by the price and updates the appropriate label with the total cost.
However, when I run the program it does not update the label. I ran the debugger and the label's .text value in the system is correct but it still does not appear on the actual form.
Is there a label property in Visual Studio that prevents changes from being rendered?
here is the snippet responsible for updating the label.Text value
if (chkSesame.Checked)
{
intSesameQty = Convert.ToInt32(txtSesameQty.Text);
decSesameTotal = intSesameQty * decBAGEL_PRICE;
lblSesameSeedTotal.Text = decSesameTotal.ToString("c");
}
Without knowing more about the structure of your form, and how you are calling your code, it's hard to give you any other advice other than to attempt to call lblSesameSeedTotal.Refresh() after setting the text.
Calling Refresh (MSDN Control.Refresh link) effectively invalidates the control and forces the runtime to redraw the control, which, of course, includes updating its text.
There are lots of reasons why you may have to do this; redrawing is an expensive operation, so, in general, if you are handling an event elsewhere on the form, it may not update certain controls. This is especially true for labels and similar controls whose values tend to remain constant (e.g. a label for a textbox with the text: Enter Name Here doesn't really need to change).
Using WPF(with C# and LinqToXml), I am reproducing a paperless version of an existing paper form. The existing form includes some one-character-per-box text strings. I have already duplicated the appearance of the paper form using XAML. How can I add code to a one-character TextBox to automatically send control to the next TextBox once it has been filled(without requiring the user to tab to the next TextBox)?
Also, these TextBox sequences facilitate the input of key field values. Once the last one-character TextBox receives a value from the keyboard, how could I code an event trigger to automatically retrieve the appropriate data record field values from the Xml data file?
Will I need to include a button on the form, or can I code the form so that the retrieval automatically occurs when the last one-character TextBox has been filled?
The neatest way to achieve what you want to do is probably to create an class representing the code that exposes the digits via properties that are bound to the textboxes (or as a string via one property and then use a ValueConverter to update the appropriate digits) and implements the INotifyPropertyChanged interface (throwing a PropertyChanged event each time the property/properties are set. You can then either create a handler that listens for PropertyChanged events from the code object, checks that all of the digits are filled in and if so loads the data from XML, or alternatively you could do that checking inside the object and raise some other event to let the application know a full code is entered.
As for how to move to the next textbox, you could create a TextChanged event handler that calls the UIElement.MoveFocus() method and register it with all of the textboxes, like so:
private void textChanged(object sender, TextChangedEventArgs e)
{
TextBox textBox = sender as TextBox;
if (textBox != null && textBox.Text.Length == 1)
{
TraversalRequest tr = new TraversalRequest(FocusNavigationDirection.Next);
textBox.MoveFocus(tr);
}
}
You may also want to set the MaxLength of each textbox to 1 to prevent copy and pasting of text, etc. and you could also look into things like ValidationRules for checking for illegal characters, etc.
Hope this helps (just ask if you need help with any of that).
Regards,
James
I have a TextBox, and a TextBlock within the Border. The TextBlock's Text property is bound to TextBox's value. When I type into the TextBox, the Border changes its width according to the TextBlock's new size.
There is an event handler for TextBox.TextChanged in which I test whether the size of the border exceeds a certain number. If it does, I want to prevent the TextBox from making the change that caused the handler.
If a character was always added to an end, I would be able just to substring the text, but all other sorts of changing can occur, for example pasting a large amount of text into the TextBox.
So, what would be the way of preventing the change from the handler? I remember in some WindowsForms e.Cancel property which when set would ignore the action, but haven't seen that in WPF and the TextChangedEventArgs obviously does not have one.
Thanks
You can listen to the PreviewTextInput event and set e.Handled to true to prevent the change from taking effect.