How to bind Command to TextChanged event of TextBox?

Topics: Prism v2 - Silverlight 3
Jul 31, 2009 at 12:51 PM
Edited Jul 31, 2009 at 12:53 PM

Hi.

I'm a beginner with Prism, so please forgive me if this question is stupid. I went through a few tutorials and I'm creating my first Silverlight application with Prism. It's composed of a Login screen and a second screen that does CRUD operations on a simple database table.

One feature is to select data using multiple filters, which are defined in TextBoxes (filters like Name, Email, Address, etc). I want to fetch data when the text of any of these textboxes chages. There will be a single command which should be invoked when any of the textboxes' text chages.

The question is how do I bind the command to the TextChanged event?

If I want to bind it to the click event of a button, that's easy, as shown in all tutorials:

<Button Content="Login" commands:Click.Command="{Binding LoginCommand}" />

 

But what about the TextChanged scenario?

Thanks.

Jul 31, 2009 at 5:59 PM

Hi

For this particular scenario you can create a command via an attached behavior that “monitors” the TextChanged event. Julian Dominguez explains the main concepts of this approach in this post. You can also check out the following post that provides a sample on how to create a command for a Silverlight DataForm particular event:

Another possible approach, if this textbox has a two way binding to a model property, could be subscribing to the property changed event and execute the command from there. This would avoid any view code behind (which is the objective of the XAML command), but saves the trouble of creating the attached behavior.

Please let me know if this helps.

Damian Schenkelman
http://blogs.southworks.net/dschenkelman

Aug 3, 2009 at 8:28 AM

Hi.

Thanks for the reply. I tried the second approach because it sounded easier (subscribing to the textchanged event), but it didn't work as I expected, because of the binding between the textboxes and the propertyes. The problem is that the value of the textbox is not reflected in the property with every change (every keypress inside the textbox), but only when the focus is lost.

What I want to do is: 

while the user types - for example - "Dan", the hanler of the event should be executed 3 times (after "D", "Da" and "Dan").

This doesn't happen, because the settter of the property in the ViewModel is only called after I press tab, or click on another visual element.

Do you know if this binding behavior can be adjusted in any way?Otherwise, I think I'll try your first suggestion.

I must admit that all these tricks and workarounds that must be implemented for even a simple (but non-trivial) application make Prism hard to love. (at least for me... at least for now).

Thanks for the help.

Aug 3, 2009 at 6:14 PM

You should look to build a KeyUp command behavior that can be applied to any UIElement. I did this to know when the enter key was pressed to trigger an action and you could use this to do the same. Have a look at the Click commanding code to model your KeyUp logic.

Once this is done, you will be able to use the event the way you need (I am assuming a MVVM pattern with this).

<TextBox x:Name="MyTextBox" lcmd:KeyUp.Command="{Binding KeyPressedCommand}" />

Let me know if you need more assistance and I can provide more when I am at my development workstation.

Aug 4, 2009 at 6:45 AM

Hi again.

I implemented the first suggestion of dschenkelman, which is very similar to what you proposed, Fred. So I monitor the TextChanged event (instead of KeyUp) and the new command fires ok, but there is still this problem:

Binding from the textboxes to the properties in the view model is not updated with TextChanged, but only when focus is lost. So When the handler of the command is executed after the first key press, let's say, the string property is still null...

Now I must find a hack to force the textbox binding to update with each key press, or else I'm lost...

But thanks again for your help. Even if I didn't solve my scenario (yet), I learned a lot of useful things from the attempts. :)

Aug 4, 2009 at 7:50 AM

There is a much simpler way to do this, and it's what I've been using so far in WPF, but I think it still applies to silverlight.
I too am new to prism and m-v-vm patterns, so please forgive me if I am off track here.

In my xaml I just bind the text property of the textbox to a property in my viewmodel class as follows: 
(the datacontext of the window is set to an instance of my viewmodel class somewhere)

<TextBox Text="{Binding Path=MyText, UpdateSourceTrigger=PropertyChanged}" />

Then in my viewmodel class I define the MyText Property:

private string _myText;
public string MyText
{
get { return _myText; }
set
{
_myText = value;
OnPropertyChanged("MyText"); // when implementing INotifyPropertyChanged
CallMyMethod(); // call any other method you want to handle when the text has changed
}

The "UpdateSourceTrigger=PropertyChanged" in the binding tells it to trigger immediately as soon as the text has changed instead of only when it loses focus.

I hope this is of help.

Jason.

Aug 4, 2009 at 8:13 AM

@Jason

For some reason, Silverlight does not support "UpdateSourceTrigger". Luckily I found a blog post which describes how to emulate that, by losing and regaining focus on the TextChanged event. It's an ugly hack and I normally would avoid such things, but it seems that currently there is no other way to get this functionality in Silverlight.