简单的TextBox文本绑定失败WPF

时间:2018-05-08 01:04:47

标签: c# wpf xaml silverlight binding

我们正在将应用程序从Silverlight转换为WPF。它是一个相当复杂的应用程序,但代码共享大约是95%+。 XAML几乎完全相同,除了XML命名空间定义等。大约90%的应用程序现在可以工作,但有一些令人费解的问题令我感到困惑。一个是这个约束性问题。

我们有一个名为TaskInfo的模型对象。它有一个名为TaskNo的属性。在Silverlight和WPF中,我们像这样绑定到这个属性

<TextBox IsReadOnly="True" Grid.Column="0"  Grid.Row="0" Margin="1" Text="{Binding Path=TaskNo}" Height="28"  Background="#CAECF4" VerticalAlignment="Center" VerticalContentAlignment="Center"  />

在WPF和Silverlight中,当TaskInfo模型首次设置为DataContext时,TaskNo会正确显示。在Silverlight中,如果我们创建一个新的TaskInfo,将其发送到服务器进行保存,并使用新的TaskNo返回模型,则会成功显示TaskNo。但是,在WPF中,当从服务器返回保存的TaskInfo时,它只显示0。绑定存在一些问题。这是我在输出窗口中看到的绑定错误:

  

System.Windows.Data信息:10:无法使用获取值   绑定并且不存在有效的回退值;使用默认值。   BindingExpression:路径= TaskNo;的DataItem = NULL;目标元素是   &#39; TextBlock的&#39; (名称=&#39;&#39);目标属性是&#39; Text&#39; (键入&#39; String&#39;)

我检查了可视化树,TextBox的DataContext按预期设置为TaskInfo。

所以,我关闭了绑定并尝试了这段代码。它是TextBox上DataContextChanging的事件处理程序。这段代码工作正常。保存并返回新任务时,TaskNo会在此处成功显示:

    private void TaskNoBox_DataContextChanging(object sender, DependencyPropertyChangedEventArgs e)
    {
        var task = TaskNoBox.DataContext as TaskInfo;
        if (task == null)
        {
            throw new Exception("Ouch!");
        }
        TaskNoBox.Text = task.TaskNo.ToString();
    }

为了进一步调试此问题,我在文本框中为GotFocus事件添加了此事件处理程序。因此,在任务已保存在服务器端并且已返回并设置为DataContext之后,我在控件内单击以触发此事件处理程序。当我单步执行此代码时,我可以看到DataContext是正确的,并且具有正确的TaskNo。调用此代码仍然不会导致绑定发生。

    private void TextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        var textBox = (TextBox)sender;
        var be = textBox.GetBindingExpression(TextBox.TextProperty);
        be.UpdateSource();
        be.UpdateTarget();
    }

TextBox文本绑定属性: enter image description here

TextBox的属性的DataContext: enter image description here

如何理解此绑定错误? Silverlight和WPF之间的绑定问题是什么?我需要某种解决方法吗?为什么绑定不起作用?

1 个答案:

答案 0 :(得分:2)

如果以前的DataContext根据Equals方法等同于新的DataContext,则WPF中的绑定永远不会更新。

Silverlight和WPF之间的区别似乎是当DataContext发生更改时,WPF似乎使用Equals方法来评估Silverlight使用引用时对象之间的差异。这意味着WPF与Xamarin.Forms相同。

我尝试了这段代码,它会导致TaskNo正确显示。我认为发生的事情是因为之前的DataContext等同于调用Equals时的新DataContext。所以,这解决了这个问题。

    private async void TaskPageHeader_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        TaskNoBox.DataContext = new object();
        TaskNoBox.DataContext = CurrentTask;
    }