1

I have a number of bindings that resemble the below code.

The bindings work fine from UI to property but wont work when I set the property in the back end code. Im not sure what's wrong here because I do have Mode=TwoWay in my XAML

public partial class app_controls : PhoneApplicationPage, INotifyPropertyChanged
{

  private String _ipAddress;
  public String ipAddressOrDomain
  {
      get { return _ipAddress; }
      set { _ipAddress = value; NotifyPropertyChanged("ipAddressOrDomain"); }
  }



  private void NotifyPropertyChanged(String propertyName)
  {
    if (PropertyChanged != null)
    {
          PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
  }
}

I am clearly binding both ways so I have no idea what the problem is.

 <telerikPrimitives:RadTextBox  BorderBrush="Black" Background="Beige" Watermark="IP Address or Domain" Text="{Binding ipAddressOrDomain, Mode=TwoWay}" TextWrapping="Wrap" Visibility="{Binding traceToolVis}" InputScope="Url"/>
DotNetRussell
  • 9,716
  • 10
  • 56
  • 111

2 Answers2

1

When I wrapped the code that is setting the property in a Dispatcher.BeginInvoke lambda it set the property no problem

When working with threading, you have to be careful not to attempt any UI-bound operations from a background thread -- that will lead to a "cross thread access exception". For example, this will throw an exception, because the property "ipAddressOrDomain" is UI-bound:

Task.Factory.StartNew(() => 
    ipAddressOrDomain = "something"       // throws exception
);

The way around this, as you noted, is to dispatch any such operations back to the UI thread:

Task.Factory.StartNew(() => {
    Deployment.Current.Dispatcher.BeginInvoke(() => 
        ipAddressOrDomain = "something"   // ok
    );
});

Side note: if you check the Output window in Visual Studio, you should see the exception appear there. The Output window is a good place to start whenever you notice a binding fail silently.

McGarnagle
  • 101,349
  • 31
  • 229
  • 260
  • Though I implemented it in my code differently, I can absolutely say that the problem was a threading issue. I never considered threading would be an issue when binding but apparently it is. – DotNetRussell May 12 '14 at 12:56
0

What you need is in the post: How to make the binding happen from the ViewModel - specifically the answer for silverlight...

public class TextChangedUpdateSourceBehavior : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.TextChanged += OnTextChanged;
    }

    private void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        var bindingExpression = AssociatedObject.GetBindingExpression(TextBox.TextProperty);

        if (bindingExpression != null)
        {
            bindingExpression.UpdateSource();
        }
    }
}

Use it like this:

<TextBox Text="{Binding TextValue, Mode=TwoWay}" Height="23" Width="300">
    <i:Interaction.Behaviors>
        <b:TextChangedUpdateSourceBehavior />
    </i:Interaction.Behaviors>
</TextBox>
Community
  • 1
  • 1
mdebeus
  • 1,928
  • 3
  • 18
  • 27
  • 1
    I've narrowed it down to a threading issue. When I wrapped the code that is setting the property in a Dispatcher.BeginInvoke lambda it set the property no problem. It was silently throwing exceptions. Will the above answer account for this? – DotNetRussell May 10 '14 at 12:56
  • 1
    @AMR this answer is way off -- you never need to manually update a binding expression for a simple two-way binding. The issue is no doubt due to accessing UI objects from a background thread. – McGarnagle May 11 '14 at 00:54