Consider a Windows Phone 7 application with a textbox and an ApplicationButton.
UI:
- <Canvas x:Name="ContentGrid" Grid.Row="1" Height="545" Width="480">
- <TextBlock Text="Enter text here" Canvas.Left="6" Canvas.Top="187" />
- <TextBox x:Name="myTextBox" Text="{Binding Test, Mode=TwoWay}" Height="69" Width="480" Canvas.Left="0" Canvas.Top="209" />
- </Canvas>
Backend:
- namespace WindowsPhoneApplication1
- {
- using System;
- using System.ComponentModel;
- using System.Windows.Controls;
- using Microsoft.Phone.Controls;
- public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
- {
- private string _test;
- // Constructor
- public MainPage()
- {
- this.InitializeComponent();
- this.DataContext = this;
- }
- public string Test
- {
- get
- {
- return this._test;
- }
- set
- {
- if (value != this._test)
- {
- this._test = value;
- this.PropertyChanged(this, new PropertyChangedEventArgs("Test"));
- }
- }
- }
- #region INotifyPropertyChanged Members
- public event PropertyChangedEventHandler PropertyChanged;
- #endregion
- }
- }
The textbox is bound to a property on the backend (two way binding) and when you click the bottom button the text is saved/send/encrypted/whatever.
Now the problem is that clicking the button doesn’t do a UI –> source binding update as it would do with a normal button.
I enter the text ‘test’ on the TextBlock and IMMIDIATLY click the ApplicationButton. I don’t do anything else. This is a common user practice, he changes something and clicks the save/send/whatsoever button.
This is the result:
Check the Watch 1. As you can see the value is still null. The value is not sent to the _test value. How do we solve this?
You can add the following line to the click event handler:
- this.myTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
So the result will look like this:
- private void AppbarButton1Click(object sender, EventArgs e)
- {
- this.myTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
- // handle save/send/encrypt/whatever here
- }
There are 3 downsides I think:
- You need to name your TextBlock which (I think) unnecessarily clutters your scope with otherwise unused variables (that’s why we use bindings too!)
- Your UI and ViewModel (in my case) aren’t decoupled 100% anymore. In Windows Phone 7 this is no issue though, since WP7 has no ICommand and I have to couply my UI and ViewModel anyway
- You need to remember to write this line! Which can be quite cumbersome with a lot of application buttons.
And items in a ApplicationBar.MenuItems (ApplicationBarMenuItem) have the same problem. The UI doesn’t push the update to the ViewModel.
I hope this will be fixed in the final version, and I will post this to Microsoft Connect. If anybody has a better solution please feel free to share it.