Set textbox to "nothing" in WPF but MV value not updated - wpf

I have a user interface where a user can enter a value and that value is updated in the ViewModel (and eventually written back to a database).
This works fine if the a value is actually entered. But if you want to clear that value (i.e. set it to nothing) it doesn't seem to work.
So for example if it was 'dog' but I clear that text and "save" the change is not recognized.
I call "PropertyChanged" which is fired if a value is entered. But if the text is cleared, and I hit enter or tab out of the textbox, the property is not updated.
Is there some special way to deal with this or am I just missing something?
thanks

It ought to work....
Are you sure your other layers (especially the DB) accept 'empty' values? It could be a conversion-exception or error being silently eaten.
To diagnose, experiment with different properties of different types.

The property will not be updated if the data type is an int.
Setting the property as a string will update the property when cleared.

As indicated by Veer in the comments above try using UpdateSourceTrigger as follows to detect when you change the text. Set a break point in your view model and see if you capture the change events when you type in the text box.
<TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

Related

ComboBox autocomplete strange behaviour

Bear with me. I have a ComboBox (WPF) in 'autocomplete' mode.
Easy peasy right? Just set IsEditable to true.
<ComboBox
IsEditable="True"
Text="{Binding Model.TextEntered}"
ItemsSource="{Binding Model.ListWithOptions}"/>
I've got my ComboBox and it autocomplete's just perfect.
BUT when I enter the following text 'caaaaa' it changes it to 'CAaaaa'. I understand the ComboBox autocomplete's the text and match the casing. But when I want to enter caaaaa (for whatever reason) I don't want 'CAaaaa'.
Any idea to solve this?
As an alternative I would settle for (if all else fails):
When leaving the control, check if entered text doesn't match any of the options set text tolower. (as a behaviour)
Have you tried setting ShouldPreserveUserEnteredPrefix="True"? This will not alter the case that is typed into the Combobox but will still match items in the list. So in your example if you type 'ca13' it will find and select 'CA132S', but it will be displayed in the combobox as 'ca132s' (in the case that it was typed in).
A compromise in the way that the item is displayed perhaps, but it will select the correct item and allow you to type characters in either case without alteration.
Try setting IsTextSearchCaseSensitive proprty to true for the ComboBox. Not sure if this property is available in older versions of .NET
Couldn't you use an if statement to check if it matches anything in the list and if it doesn't, don't change it? Like check after each letter entered and if it then doesn't match change it back to the case that was originally entered?
Or is there a reason you want people to be able to type in something that isn't in the list? If not, couldn't you use IsTextSearchEnabled rather than IsEditable?

Getting the current culture date pattern in XAML code

So in my (large) project, I've got a special date box that derives from a masked text box and thus has a "Format" property. It works by giving it a short date format, such as:
<extended:DateMaskTextBox Format="yyyy-MM-dd" />
Now at the start of the application, the ShortDatePattern property of the CultureInfo.CurrentCulture.DateTimeFormat object is set, depending on some logic. I would like to obtain this ShortDatePattern to use it as a value for my Format property of my DateMaskTextBox.
So far I've got this, and it is not working:
<extended:DateMaskTextBox Format="{Binding Source={x:Static glob:CultureInfo.CurrentCulture}, Path=DateTimeFormat.ShortDatePattern}" />
Any idea why this does not work? Thanks.
That Binding syntax is correct and should work just fine. Are you getting any binding errors in your output window? Have you tried displaying that same Binding on a TextBlock.Text in place of your control to just see if the string is coming through?
Without seeing its code I can't tell but I suspect that the problem may be with the DateMaskTextBox rather than the Binding. If the control is not set up correctly to respect newly set values of its Format property the bound value may not be getting used at all or be getting used too late to affect the behavior you're seeing when interacting with the control.

Data binding: Different triggers for different purposes

I have a WPF MVVM data form window with data validation. A lot of the controls are text boxes. Currently, the data binding trigger is set to the default, i. e. loss of focus. This means that a field is only validated when it is likely to be filled out completely. So when deleting a number and typing another number, the transient empty value will not be displayed as input error.
But a drawback is that the Save button can only be enabled when the focus moves out of the text box. (No matter where, just out of the edited control. Assuming there is anything else focusable.) If this is the only change, the user waits for the Save button to be available and nothing happens. For the Save button, I'd like to use an immediate binding trigger. How can that be done?
Edit: Forgot to mention that my Save button (which uses ICommand) is only enabled when the input is determined modified and valid. So the data will remain unmodified until data binding updates it, and that won't happen until the focus moves to another control.
I actually had a similar question a while back and the solution I ended using was a custom DependencyProperty that kicked off a timer when a key was pressed, and only actually processed the PropertyChange notification if a specific time had passed.
This means the bound property doesn't get updated (and validated) unless the user pauses in typing for a set period of times.
The code can be found here (may need a bit of cleanup), and it is used like this:
<TextBox
local:DelayedUpdateBehavior.TargetProperty="{x:Static TextBox.TextProperty}"
local:DelayedUpdateBehavior.Milliseconds="1000"
Text="{Binding MyTextProperty, UpdateSourceTrigger=Explicit}" />
Edit: Actually this link might be better. It's a markup extension so you can use it directly from your binding. I can't remember which of these two methods I used in the past, but I know it was one of them :)
<TextBox Text="{local:DelayBinding Path=MyTextProperty, Delay='00:00:01'}" />
Assuming you're using an ICommand type interface for the button click event:
You can...Implement string properties with INotifyPropertyChanged and bind them to your textbox controls. Now in your Command canexecute method you can check to see if the property is !nullorempty.
e/ grammar
Set your Binding's UpdateSourceTrigger property to PropertyChanged. The default for TextBoxes is LostFocus.
Update: So you want to have data binding working on your TextBox and only allow numbers? Have a look at this question: Create WPF TextBox that accepts only numbers
Or use a converter and bind the Save button's IsEnabled property to your TextBox (maybe using a MultiBinding if there's more than one), and use a converter which determines if the text is a valid number and returns true or false.

UI IsDirty versus Entity IsDirty

I am well aware of the INotifyPropertyChanged and INotifyCollectionChanged for WPF binding. This has been implemented and is working as expected. Therefore, changes to a property on our entities will set their "IsDirty" flag. Which in turn, turns on the Save functionality, all via binding, beautiful you may say.
However, we recently had a change request raised to request that the Save button should become enabled as soon as the field changes (i.e. use presses the first keystroke), much like the undo application command does when you type in a textbox. Therefore the save button must know when every field is changed on the form instead of the property being changed in the entity via binding.
The main reason for this request for help, is one of our forms only has one field that changes (everything else normally remains default), but the user still has to tab out of the field to enable the Save button, instead of just being able to save straight away.
You need to change the UpdateSourceTrigger to PropertyChanged
This will update the binding everytime the text changes rather than LostFocus - which is the default for a textbox.
<TextBlock Name="txtName" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />

WPF DataGrid with textbox in template column not firing property changed

I have a datagrid with a template column, and in that template is a textbox. It's bound to the 'Quantity' property of the object in the collection that makes up itemssource. Quantity is an integer. When I add an item to the datagrid, I am adding an event handler to the PropertyChanged event of the item:
EnteredPart.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(p_PropertyChanged);
This works fine when the user enters an integer in the textbox... the p_PropertyChanged handler fires and I can disable buttons and alter quantities as necessary. When the user enters a non-integer, the handler doesn't get called, I just get a red outline around the textbox. Because of this, I can't disable the necessary buttons when I need to (they should be disabled with the quantity is not legit.) Is there any way that I can do something about this?
EDIT: I tried changing the Quantity property to a string, and this caused the property changed handler to be called when non-integral values are entered. However, I then added validation to the textbox to check for this, and if the Validate method returns false, the property changed handler once again ceases to be hit. Is there any way at all to get both validation and property changed notifications??
EDIT 2: Here another instance of this problem I'm having, in another location. I have a form for adding/editing phone numbers. The phone number textbox looks like this:
<TextBox >
<TextBox.Text>
<Binding Path="Phone.Number">
<Binding.ValidationRules>
<local:PhoneValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Upon clicking a save button, I need to check in my viewmodel if the number is valid, because if it's not, I don't want to run the save command. However, it doesn't seem as if there's any way to do that, because if the validation fails, then the Phone.Number property has a null value, and I have no way to check to see if I should run the save command. I either need access to the error state (which I thought would work by Validation.GetErrors, but doesn't), or to the actual text within the textbox, which isn't available in the viewmodel.
Just for the record, validation in the View part has many drawbacks if you are in an MVVM architecture.
You'd try here to check your model's content, in the view: you'd therefore break MVVM's architecture by calling your model in the view.
Using IDataErrorInfo will help you to fulfill MVVM's main objective (ie. clearly separate the three parts).
Just an example:
I think here you are just performing a very small validation (just check if it is an int or not).
But in a different environment, assume that your model is much more complicated and needs a deeper validation. Using IDataErrorInfo will help you to check deeply in your model without calling it from the view.
As a matter of fact, in my personal experience, as I regularly work with large and highly correlated datasets, I cannot even picture using validation without IDataErrorInfo because it'd cost me too much to investigate in all the data presented and find potential errors

Resources