WPF RaisePropertyChanged event on lost focus - c#

I have a C# WPF MVVM application that works fine.
The only problem is when I modify a textbox and click on the menu. If I do that without clicking on another control, the view->viewmodel event is never fired because the textbox hasn't lost focus. Correct me if I am wrong, but I think the RaisePropertyChanged is only fired on LostFocus (or OnBlur, or any similar event).
So, clicking on the menu save button right after editing the textbox causes the viewmodel to save the data using old values.
So, resuming:
This sequence works fine:
Edit the text box
Click on another control
RaisePropertyChanged is fired, the viewmodel is updated
Click on save button on the menu
Data Saved with correct values
This sequence gives me an error:
Edit the text box
Click on save button on the menu
Data Saved with correct values
How to solve this?

This is a common gotcha with TextBoxes in both WPF and WinForms. You can get around this by instructing the binding system to update the VM with every change to the TextBox instead of when it loses focus. To do this, set the UpdateSourceTrigger of the binding to PropertyChanged. This will write back to the VM any time the TextBox raises the PropertyChanged event for its Text property.
<TextBox Text="{Binding MyText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

For the TextBox.Text dependency property, its default UpdateSourceTrigger is LostFocus (ie, your view model property gets updated when the control loses focus). To make the property update immediately whenever text is entered, set UpdateSourceTrigger=PropertyChanged. (See the link above for more info -- it actually covers your example specifically.)

Related

Set textbox as focused element

I am trying to set focus on a text box. I tried set focus for cursor
but all that does is put the cursor there and freezes it. You can't actually type anything still. You end up still having to click the text box to type. I did exactly as they did in that question. I read some stuff about logical focus and physical focus? Not quite sure how to go about doing what I need. Do I need to create an attached property and handle it that way? I am trying to avoid code behind at all costs.
Also, after clicking a "Submit" button I would like to have it set focus back to the text box again
Here is the code I tried, the FocusManager is on a grid that wraps the textbox:
FocusManager.FocusedElement="{Binding ElementName=FocusedTextBox}"
<TextBox Text="{Binding serialNumber}"
x:Name="FocusedTextBox">
</TextBox>
As I said, all this did is put the cursor there and you can't type anything until you again click in the text box. Any suggestions?
Thanks,
Just give the textbox a name (e.g. "theTextBox') and call theTextBox.Focus().
If you're trying to do this in MVVM with data-binding (and you should be) then you can use an attached property to bind to a property in your view model.

Get a change event when the value bound to TextProperty is changed for Decended TextBox

I have my own custom TextBox class (call it MyCustomTextBox). In part it helps me handle scans from a barcode reader.
Part of what I need for this to work is a way to capture when the value bound to TextProperty changes.
Note: I am not looking for the "TextChanged" event or any kind of event that relates to a key press (except when that key press updates the source).
Here is an example:
I need an event (in MyCustomTextBox) that will fire ONLY when the underlying value (CustomerId) gets changed.
Note: The actual TextProperty gets changed every time a key press happens. But the Source is not updated until later (depending on your UpdateSourceTrigger setting). The TextProperty changes too frequently for what I am trying to do. So attaching to it will not help me.
Is there any way to attach to the value under the TextProperty?
Is this possible?
Yep, you need to hook up 2 events though
<TextBox Name="Fred" Text="{Binding Foo, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, UpdateSourceTrigger=LostFocus}" TargetUpdated="Fred_TargetUpdated" SourceUpdated="Fred_SourceUpdated">
TargetUpdated event will get fired when something other than the textbox changes the underlying property (and when it first binds) eg. some method in your VM say
Sourceupdated event will get fired when your textbox updates its binding eg on lost focus

What Textbox event is raised right after bound data source is updated?

In windows forms, when I tab out of a text box, the bound data source value is updated. I'd like to capture the events right before and right after the data source changed. I think the OnLeave event is what I want for the before event. In the debugger, I'm not seeing the data source value changed. But, what event can I key off of for the after event?
I don't think there is an event that does exactly what you're asking, the closest I think you're going to get is to use the DataBindings and find your specific Binding and the you can catch the Parse event. But I believe this event fires before the data is pushed back to the source, so it's not much better than the LostFocus event.
The default event for TextBox DataBindings is DataSourceUpdateMode.OnValidation. When you tab out of the TextBox, the following events will fire:
Leave
Validating
(data source gets updated)
Validated
The Validating event has a CancelEventArgs parameter that allows you to cancel the leave attempt for the TextBox (the focus will remain in the TextBox).
If you use DataSourceUpdateMode.OnPropertyChanged, it will update the data source with every keystroke or text change.

Conditional binding using mvvm light on wp7

Hi, Please consider the custom wp7 message box above. I am looking to see what is the cleanest way to bind a views textbox to a property on the view model only after a button is clicked. The only way I can work out is to have two properties and use a command on the button to assign the value of the first prop to the main prop. The main prop should only receive the value from the textbox only if the user clicks the tick button and not if they cancel (by pressing the back button).
I am using MVVM Light.
What about catching the click event and sending the changed text from View to ViewModel via Messenger. On ViewModel the property would be only a getter.
I think that the way you do it is ok.
Have a temporary binded property and main property synced with the temporary one only when messagebox is accepted.

C# How to commit a TextBox?

In a form, I have a TextBox Binding an Object on its member property "Title". Along with it is a "Save" button to test the binding.
Seems like the underlying object property does not get updated unless the textbox loses focus. But there no form.ActiveControl.Blur() for use. Besides, this does not seem like a sound hack.
Anyway to do this better? Thanks.
EDIT: Sorry for not being clear. My question is in the title: "How to commit a TextBox". I use the term "commit" from the DataGridView commit and BindingSource commit. And it's in WinForms. (Have never worked with WPF, so it didn't occur to me. Sorry).
The actual scenario I have is I have a bunch of TextBox binded to property of a single Object. The user enters values in all the TextBox and when the user clicks save (toolbar button), the last TextBox is still in focus (or in editing mode) hence the save will not capture the last value in the last textbox.
I want to find the correct way to "commit" the textbox value just before saving.
Thanks.
Since the question has been updated to indicate this is WinForms, you'll need to handle things a little differently than if this were a WPF application. Fortunately, it turns out that the solution is very simple.
Whenever the user clicks on the "Save" button (so, say, in your Save button's Click event handler), you need to call the EndEdit method on your BindingSource. This will cause all pending changes to be committed to the underlying data source, exactly what you were hoping to accomplish.
Also see the relevant documentation on MSDN for more details.
Sounds like WPF from the problem description..
You want to change the binding so that it updates when the property value changes instead of when the textbox loses focus (which is the default when binding to TextBox.Text). You can do this by setting the UpdateSourceTrigger property on your binding:
<TextBox Text="{Binding UpdateSourceTrigger=PropertyChanged}"/>

Categories