Question

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"/>
Was it helpful?

Solution

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.

OTHER TIPS

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>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top