1
votes

I've got a textbox in a WPF window that's bound to a string proprty in my ViewModel. I also have a button that is bound to a command. The button is the default button in the window so that when enter is pressed, the command runs. The command is only enabled when the textbox is not empty.

If I type into the textbox, then hit enter, all works as expected.

However, this textbox is also the place that receives barcodes from a barcode scanner that adds codes to the keyboard buffer. The barcode scanner "types" the barcode and presses Enter (this is working).

The problem is, if the textbox is empty, the barcode scanner fills it but the Enter is not captured becaue the command has yet to become available. If the textbox starts with something in it everything works when the barcode is scanned.

My binding is:

Text="{Binding Barcode,UpdateSourceTrigger=PropertyChanged}"

The property of the ViewModel notifies via INotifyPropertyChanged and I also tried running CommandManager.InvalidateRequerySuggested() to try to get the command to become available but to no avail.

2
How is the command defined? How does the CanExecute() method or action look like?RoelF
public DelegateCommand AddAssetCommand { get { if (_addAssetCommand == null) _addAssetCommand = new DelegateCommand( e => { AddAsset(); }, c => { return !string.IsNullOrWhiteSpace(Barcode); }); return _addAssetCommand; } }BlackWasp
Hmm. That didn't come out well but hopefully you can see the bit you asked for.BlackWasp
Just thinking out loud here: depending on how consistent the input is from the bar code scanner you might be able to achieve this without relying on the default enter button. Could the the string property in your view Model using tracking logic to see a new bar code is entered and complete and then just trigger the command with a direct call?Tod

2 Answers

0
votes

CommandManager.InvalidateRequerySuggested should have worked; however I think it is also asynchronous, so if the scanner sends keystrokes very fast it may send the enter before WPF has the chance to update everything. Try to intercept the enter and delay it a bit, maybe with Dispatcher.BeginInvoke?

Or invoke CommandManager.InvalidateRequerySuggested with Dispatcher.Invoke with a high priority (Send is the highest I think).

Edit: Also, the default behavior of the TextBox is only to update the Binding on LostFocus, I assume you changed that to PropertyChanged? Nevermind, saw it in your question.

0
votes

If InvalidateRequerySuggested did not work, you may want to go to an easier route, and just remove your CanExecute constraint, and instead disable the button directly when the Barcode value is empty.

By the way, are you using Prism's DelegateCommand? If that is the case, then InvalidateRequerySuggested is not used at all by it, and instead it uses a method called RaiseCanExecuteChanged on the command, to trigger an update on the UI. This removes WPF's visual tree from the picture to avoid degrading perfomance, assuming you have all the information to respond to a CanExecute request in your viewmodel.