4

I have a TextBox in my app, and an ApplicationBarIconButton in the ApplicationBar which acts as a "submit" for the contents of the TextBox.

When editing the TextBox using the virtual keyboard, the ApplicationBarIconButton is still visible below the SIP, so you can submit straight away without dismissing the keyboard: nice!

However, when clicking the button, the viewmodel to which the TextBox is bound does not update.

I found someone else with the same problem here, and they have used the pretty nasty workaround of manually updating the viewmodel on the TextBox's TextChanged event.

Removes all the elegance of using databound view models!

Is this a bug in WP7?

Or is there a nicer way around this that I haven't found yet?

funkybro
  • 8,432
  • 6
  • 39
  • 52
  • 2
    Broken link :( All links to Microsoft sites should contain the full page title, because we all know Microsoft like to shuffle their entire web prescence every 6 months, breaking all existing links, even the ones they use in their products! – Greg Woods May 09 '13 at 15:14
  • Seems to be duplicate of http://stackoverflow.com/questions/5569768/textbox-binding-twoway-doesnt-update-until-focus-lost-wp7 - which contains a good suggestion to use Prism's UpdateTextBindingOnPropertyChanged behaviour – Greg Woods May 14 '13 at 08:55

3 Answers3

13

The problem is that silverlight bindings do not support the PropertyChanged value for UpdateSourceTrigger. This means that by default a TextBox will update the property bound to Text when the TextBox loses focus and the only other possibility is to update it explicitly in code as is done in the example from your link.

You only really have two options here: Update the binding when the button is clicked or remove focus from the TextBox when the button is clicked.

I usually update the binding on the TextChanged event. I use an extension method to do this:

public static void UpdateBinding(this TextBox textBox)
{
    BindingExpression bindingExpression = 
            textBox.GetBindingExpression(TextBox.TextProperty);
    if (bindingExpression != null)
    {
            bindingExpression.UpdateSource();
    }
}

allowing me to just call this in code behind:

textBox.UpdateBinding();

You may also be able to use a custom behaviour for this.

calum
  • 1,580
  • 10
  • 11
  • Thanks. I suspect it's also a consequence of the ApplicationBar and its friends not being real Silverlight framework elements: http://blogs.msdn.com/b/ptorr/archive/2010/06/18/why-are-the-applicationbar-objects-not-frameworkelements.aspx – funkybro Nov 18 '11 at 08:01
1

Summary of the steps to allow binding to work for each keypress of a textbox, instead of just when the text box loses focus. Uses Prism. It is a slightly indirect solution to the original problem.

  • In NuGet package manager, search for Prism. Add "Prism.Phone" created by "Microsoft patterns & practices"

  • Add the following to the page's phone:PhoneApplicationPage tag

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:prismInteractivity="clr-namespace:Microsoft.Practices.Prism.Interactivity;assembly=Microsoft.Practices.Prism.Interactivity"

  • Give your textbox a separate closing tag, and add the following between the opening and closing TextBox tags

<i:Interaction.Behaviors> <prismInteractivity:UpdateTextBindingOnPropertyChanged/> </i:Interaction.Behaviors>

Greg Woods
  • 2,697
  • 2
  • 26
  • 18
0

I guess this will work but you should check if it is really necessary having an ApplicationBarIconButton (or simply a button on the page) for that.

Often you should avoid this when you like to have a good Metro design in your app you may prefer using InputScope="Search" + Hiding the SIP is easily done using Page.Focus()

e.g. (an old article; InputScope="Search" worked for me) http://4mkmobile.com/2011/02/wp7-devs-stop-adding-search-buttons/

See also: http://forums.create.msdn.com/forums/p/70506/619517.aspx#619517

private void SearchTextBox_KeyUp(object sender, KeyEventArgs e) handler:

  1. Using InputScope="Search" for my search field
  2. Using DataBinding Mode=TwoWay
  3. Focus(); // hides the SIP
  4. UpdateBinding(SearchTextBox); // the trick mentioned in here
  5. App.ViewModel.ExecuteSearch();

Works fine in my MVVM app.

hfrmobile
  • 1,213
  • 16
  • 16