【问题标题】:Weird binding not working奇怪的绑定不起作用
【发布时间】:2014-05-10 03:47:33
【问题描述】:

我有许多类似于以下代码的绑定。

从 UI 到属性的绑定工作正常,但当我在后端代码中设置属性时无法正常工作。我不确定这里出了什么问题,因为我的 XAML 中确实有 Mode=TwoWay

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));
    }
  }
}

我显然是双向绑定的,所以我不知道问题出在哪里。

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

【问题讨论】:

  • 我正在设置 ipAddressOrDomain
  • 更好的是,如果我继续对其执行操作,UI 将正确响应。它只是不显示它
  • 是的,我刚试过。整个应用程序都是一样的。我的 XAML 中一定有什么奇怪的东西阻止了它。

标签: c# windows-phone


【解决方案1】:

当我将设置属性的代码包装在 Dispatcher.BeginInvoke lambda 中时,它设置属性没有问题

使用线程时,您必须小心不要从后台线程尝试任何 UI 绑定操作——这将导致“跨线程访问异常”。例如,这将引发异常,因为属性“ipAddressOrDomain”是 UI 绑定的:

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

正如您所说,解决此问题的方法是将任何此类操作分派回 UI 线程:

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

旁注:如果您在 Visual Studio 中检查“输出”窗口,您应该会看到异常出现在那里。每当您发现绑定失败时,“输出”窗口是一个很好的起点。

【讨论】:

  • 虽然我在代码中实现它的方式不同,但我绝对可以说问题是线程问题。我从不认为绑定时线程会是一个问题,但显然它是。
【解决方案2】:

您需要的是帖子中的内容:How to make the binding happen from the ViewModel - 特别是 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();
        }
    }
}

像这样使用它:

<TextBox Text="{Binding TextValue, Mode=TwoWay}" Height="23" Width="300">
    <i:Interaction.Behaviors>
        <b:TextChangedUpdateSourceBehavior />
    </i:Interaction.Behaviors>
</TextBox>

【讨论】:

  • 我已将其缩小到线程问题。当我将设置属性的代码包装在 Dispatcher.BeginInvoke lambda 中时,它设置属性没有问题。它默默地抛出异常。上面的答案会解释这个吗?
  • @AMR 这个答案太离谱了——您永远不需要为简单的双向绑定手动更新绑定表达式。这个问题无疑是由于从后台线程访问 UI 对象造成的。
猜你喜欢
  • 2015-07-19
  • 1970-01-01
  • 1970-01-01
  • 2012-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多