.NET 3.5 | 绑定到视图模型属性时,WPF Textbox拒绝更新自身

在我开始解释我的问题之前,请注意我的目标框架是.NET 3.5。

我有一个文本框,其文本绑定到viewmodel属性。 我的要求是,当用户输入一些东西(通过键盘和鼠标粘贴)进入文本框时,应该清理其中的任何垃圾字符,并使用替换的字符串更新文本框[在下面的示例中”要替换用’h’]。

XAMLCode:

                      

ViewModel属性:

  private string _value; public string Value { get { return _value; } set { if (_value == value) return; _value = value; //replaces 's' with 'h' and should update the textbox. _value = _value.Replace('s','h'); RaisePropertyChanged(() => Value); } } 

以上根本不适合我。 视图模型属性设置器正在触发…值正在被替换。但是文本框没有得到更新。 令人困惑的是,这完全适用于.Net4.0。

你知道为什么这不会工作以及这个问题的潜在解决方案,当然除了升级到.NET 4.0之外?

我的要求:

  • 用户可以键入以及将任何内容粘贴到多行文本框中。

  • 文本可以包含垃圾,在进入文本框之前应该更改垃圾。

提前谢谢,-Mike

我遇到了一个非常类似的问题,我想要双向绑定,我正在修改ViewModel中的值,并希望在TextBox中看到更新。 我能够解决它。 虽然我使用的是.NET 4.0,但我基本上也遇到了同样的问题,所以这也许值得你试试3.5的情况。

简答:

我遇到的是一个错误, TextBox's显示文本与TextBox's自己的Text属性的值不同步。 Meleak对类似问题的回答使我对此有所了解,并且我能够使用Visual Studio 2010中的调试器以及使用Meleak的TextBlock技术来validation这一点。

我能够通过使用显式绑定来解决它 。 这需要处理UpdateSource()UpdateTarget()在后面的代码中自我发布(或者在我最终做的自定义控制代码中,以便更容易重用)。

进一步说明:

这是我处理显式绑定任务的方式。 首先,我有一个TextChanged事件的事件处理程序,它更新了绑定的来源:

 // Push the text in the textbox to the bound property in the ViewModel textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource(); 

其次,我有一个TextBox的Loaded事件的事件处理程序。 在那个处理程序中,我为ViewModel的PropertyChanged事件注册了一个处理程序(ViewModel是这里的“DataContext”):

 private void ExplicitBindingTextBox_Loaded(object sender, RoutedEventArgs e) { TextBox textBox = sender as TextBox; if (textBox.DataContext as INotifyPropertyChanged == null) throw new InvalidOperationException("..."); (textBox.DataContext as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(ViewModel_PropertyChanged); } 

最后,在PropertyChanged处理程序中,我使TextBox从ViewModel中获取值(通过启动UpdateTarget())。 这使得TextBox从ViewModel获取修改后的字符串 (在您的情况下是带有替换字符的字符串)。 在我的情况下,我还必须在刷新文本(从UpdateTarget())后处理恢复用户的插入位置。 但是,这部分可能适用于您的情况,也可能不适用于您

  ///  /// Update the textbox text with the value that is in the VM. ///  void ViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { // This textbox only cares about the property it is bound to if (e.PropertyName != MyViewModel.ValueStrPropertyName) return; // "this" here refers to the actual textbox since I'm in a custom control // that derives from TextBox BindingExpression bindingExp = this.GetBindingExpression(TextBox.TextProperty); // the version that the ViewModel has (a potentially modified version of the user's string) String viewModelValueStr; viewModelValueStr = (bindingExp.DataItem as MyViewModel).ValueStr; if (viewModelValueStr != this.Text) { // Store the user's old caret position (relative to the end of the str) so we can restore it // after updating the text from the ViewModel's corresponding property. int oldCaretFromEnd = this.Text.Length - this.CaretIndex; // Make the TextBox's Text get the updated value from the ViewModel this.GetBindingExpression(TextBox.TextProperty).UpdateTarget(); // Restore the user's caret index (relative to the end of the str) this.CaretIndex = this.Text.Length - oldCaretFromEnd; } }