AvalonEdit中的双向绑定不起作用

我在我的项目中使用了AvalonEdit,它基于WPF和MVVM。 看完这篇文章后,我创建了以下课程:

public class MvvmTextEditor : TextEditor, INotifyPropertyChanged { public static DependencyProperty DocumentTextProperty = DependencyProperty.Register("DocumentText", typeof(string), typeof(MvvmTextEditor), new PropertyMetadata((obj, args) => { MvvmTextEditor target = (MvvmTextEditor)obj; target.DocumentText = (string)args.NewValue; }) ); public string DocumentText { get { return base.Text; } set { base.Text = value; } } protected override void OnTextChanged(EventArgs e) { RaisePropertyChanged("DocumentText"); base.OnTextChanged(e); } public event PropertyChangedEventHandler PropertyChanged; public void RaisePropertyChanged(string info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } } 

并使用以下XAML来使用此控件:

          

但绑定工作OneWay并不更新我的字符串属性也不运行validation规则。

如何修复绑定以按预期工作TwoWay

WPF绑定不使用您的DocumentText属性; 相反,他们直接访问依赖属性的基础值。

OnTextChanged方法实际上不会更改基础依赖项属性的值。 您需要在每次更改时将base.Text的值复制到依赖项属性中:

 protected override void OnTextChanged(EventArgs e) { SetCurrentValue(DocumentTextProperty, base.Text); base.OnTextChanged(e); } 

如果您遵循正确的模式来实现DependencyProperty则会更容易看到此问题: DocumentText属性应使用GetValue / SetValue方法,而不是访问其他后备存储。

即使使用GetValue和SetValue,也无法让TextProperty在文本更改时更新绑定,因此无论如何都必须遵循Daniel的回答。

我确实做了一些改动,使最终用户不得不使用Text作为普通和依赖模式更直观:

  public new string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } internal string baseText { get { return base.Text; } set { base.Text = value; } } public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(MvvmTextEditor), // binding changed callback: set value of underlying property new PropertyMetadata((obj, args) => { MvvmTextEditor target = (MvvmTextEditor)obj; if(target.baseText != (string)args.NewValue) //avoid undo stack overflow target.baseText = (string)args.NewValue; }) ); protected override void OnTextChanged(EventArgs e) { SetCurrentValue(TextProperty, baseText); RaisePropertyChanged("Text"); base.OnTextChanged(e); } 

我必须检查是否已存在相同的文本以避免撤消堆栈引擎exception。 表现明智也是一个很好的协议。

我尝试了基于上面的答案的代码稍作修改,因为绑定对我来说两种方式都不起作用。 下面的内容应该允许绑定两种方式。

  public static readonly DependencyProperty MyContentProperty = DependencyProperty.Register( "MyContent", typeof(string), typeof(MyTextEditor), new PropertyMetadata("", OnMyContentChanged)); private static void OnMyContentChanged(object sender, DependencyPropertyChangedEventArgs e) { var control = (MyTextEditor)sender; if (string.Compare(control.MyContent, e.NewValue.ToString()) != 0) { //avoid undo stack overflow control.MyContent = e.NewValue.ToString(); } } public string MyContent { get { return Text; } set { Text = value; } } protected override void OnTextChanged(EventArgs e) { SetCurrentValue(MyContentProperty, Text); base.OnTextChanged(e); }