简单的 TextBox 文本绑定失败 WPF

Posted

技术标签:

【中文标题】简单的 TextBox 文本绑定失败 WPF【英文标题】:Simple TextBox Text Binding Fails WPF 【发布时间】:2018-10-17 20:39:47 【问题描述】:

我们正在将应用程序从 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:无法使用 绑定且不存在有效的后备值;改用默认值。 绑定表达式:路径=任务编号;数据项=空;目标元素是 '文本块'(名称='');目标属性是“文本”(类型“字符串”)

我检查了可视化树,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 文本绑定属性:

TextBox 属性的DataContext:

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

【问题讨论】:

【参考方案1】:

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

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

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

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

【讨论】:

这适用于 WPF 中的所有依赖项属性。如果您再次分配相同的值,则不会触发任何属性更改操作。 是的。这听起来很对。不同之处在于,在 Silverlight 中,等效性由对象引用确定,而在 Xamarin.Forms 和 WPF 中,等效性由 Equals 方法确定。

以上是关于简单的 TextBox 文本绑定失败 WPF的主要内容,如果未能解决你的问题,请参考以下文章

WPF 数据验证中的绑定失败

C# WPF .Net4.8 Framework ReadOnly TextBox 文本绑定延迟更新

如何在文本更改时启用/禁用绑定到 ICommand 的按钮,而不是失去 TextBox 的焦点

如何设置绑定到文本框的标签的可见性?

使用文本框的值绑定Datagrid

WPF 怎么使数据和textbox绑定 使textbox具有文字追加效果