1

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.

ygoe
  • 18,655
  • 23
  • 113
  • 210
  • 1
    There comes a point in every young man's life where he has to accept the fact that his UI logic is too complex, and so he moves into his very own UserControl where he can throw his socks about in his codebehind without anybody yelling at him. –  Jul 19 '12 at 13:59

3 Answers3

1

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'}" />
Community
  • 1
  • 1
Rachel
  • 130,264
  • 66
  • 304
  • 490
0

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

ecMode
  • 530
  • 3
  • 16
  • Yes, I am using ICommand for the button. But the button is disabled until the input is modified and valid. (Did I forget to mention that...) So the button cannot be clicked until the data is determined modified, which only happens after it has been updated, for which the focus must switch. If you only make one change and want to save it, you still need to focus another textbox first or the button remains disabled. – ygoe Jul 19 '12 at 13:11
-1

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.

Community
  • 1
  • 1
Zak
  • 724
  • 4
  • 18
  • But then, an error will be visible when the input is invalid but when the user isn't even finished typing it! See question above. – ygoe Jul 19 '12 at 13:08