Real Time Binding with Windows Phone

Recently while developing a new app for Windows Phone I ran into a strange problem.  Using Caliburn.Micro I set up a binding with a simple TextBox control.  Also on the page in an Application Bar Button which raises a Save action method in the view model.  The bug was that every time I saved the entity, the Name would be null in the backend service.  The debug process revealed that the Property Update for the Name was happening AFTER the Save method.

Reading the documentation and posts by other developers I discovered that the default mode for source updates happens on “Lost Focus” and that, for whatever reason, when the user presses an Application Bar Button the control does NOT actually lose focus, thus the property update happens AFTER the view model method is executed.  In Silverlight and WPF, you can set the UpdateSourceTrigger to PropertyChanged which will handle this case.

Unfortunately, for whatever reason, Windows Phone Silverlight does not support this feature so the only option is to update on focus, which obviously doesn’t work.  However, this feature is available with some support from the Microsoft Patterns & Practices Prism framework in the UpdateTextBindingOnPropertyChanged custom behavior.  Here is the source for the class:

   1:      public class UpdateTextBindingOnPropertyChanged : Behavior
   2:      {
   3:          private BindingExpression expression;
   4:   
   5:          protected override void OnAttached()
   6:          {
   7:              base.OnAttached();
   8:   
   9:              this.expression = this.AssociatedObject.GetBindingExpression(TextBox.TextProperty);
  10:              this.AssociatedObject.TextChanged += this.OnTextChanged;
  11:          }
  12:   
  13:          protected override void OnDetaching()
  14:          {
  15:              base.OnDetaching();
  16:   
  17:              this.AssociatedObject.TextChanged -= this.OnTextChanged;
  18:              this.expression = null;
  19:          }
  20:   
  21:          private void OnTextChanged(object sender, EventArgs args)
  22:          {
  23:              this.expression.UpdateSource();
  24:          }
  25:      }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

What this behavior is doing is attaching itself the given control and calling UpdateSource on a custom binding which will force the source to update.  In this case, we are associating this source update with the TextChanged event which will cause the property to update as the value of the Textbox changes. (Side note: you will also need to include the System.Windows.Interactivity to get the Behavior project).

Now, to actually use this class, you will need to write some code behind, just two lines.  There might be a way to get this into the declarative binding syntax in the XAML, but I do not know how to do that.  Here is the code which adds this behavior, it is in the constructor just after the InitalizeComponent.

        public SaveLocationView()
        {
            InitializeComponent();
 
            // manual bindings
            var behavior = new UpdateTextBindingOnPropertyChanged();
            System.Windows.Interactivity.Interaction.GetBehaviors(tbName).Add(behavior);
        }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Very simple, hence why I didnt pursue trying to get it into the binding syntax.  This correctly fixes the problem with the updating.  I hope people find this helpful, and I do hope Microsoft makes this functionality native in future versions.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s