2013-02-13 9 views
8

WPFとMVVMをベースにしたプロジェクトでAvalonEditを使用しました。 はthis postを読んだ後、私は次のクラスを作成しました:AvalonEditでの双方向バインディングが機能しません。

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を使用:

<avalonedit:MvvmTextEditor x:Name="xmlMessage"> 
    <avalonedit:MvvmTextEditor.DocumentText> 
     <Binding Path ="MessageXml" Mode="TwoWay" 
       UpdateSourceTrigger="PropertyChanged"> 
     <Binding.ValidationRules> 
      <local:XMLMessageValidationRule /> 
      </Binding.ValidationRules> 
     </Binding> 
    </avalonedit:MvvmTextEditor.DocumentText> 
</avalonedit:MvvmTextEditor> 

が、結合作品OneWayと私の文字列プロパティを更新したり、検証を実行しません。ルール。

バインディングをどうすれば正常に動作させることができますか?TwoWay

+0

どうすればこのことができますか?私は別の質問[ここ](http://stackoverflow.com/questions/18964176/two-way-binding-to-avalonedit-document-text-using-mvvm?noredirect=1#comment28010773_18964176)... – MoonKnight

答えて

6

WPFバインディングでは、DocumentTextプロパティは使用されません。代わりに、依存関係プロパティの基になる値に直接アクセスします。

OnTextChangedメソッドは、基本となる依存関係プロパティの値を実際に変更しません。あなたはすべての変更に依存関係プロパティにbase.Textから値をコピーする必要があります。

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

この問題は、あなたがDependencyPropertyを実装するための正しいパターンに従ったかどうかを確認するために容易になるだろう:DocumentTextプロパティはGetValue/SetValueを使用する必要があります異なるバッキングストアにアクセスすることはできません。

+1

ありがとう返事のために非常に - 私は助けた。私は 'MvvmTextEditor'クラスのための上記のコードで' GetValue'/'SetValue'を使う方法について混乱していますか?現在の実装と互換性がないようです。 – MoonKnight

4

GetValueとSetValueを使用しても、テキストが変更されたときにバインドされたTextPropertyを更新することはできません。したがって、とにかくDanielの回答に従わなければなりません。同じテキストを避けるために、すでにあった場合、私がチェックしなければならなかった

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

私はノーマルとdependecyモードとしてテキストを使用したエンドユーザーにそれがより直感的にするためにビットを変更しましたスタックエンジンの例外を取り消します。パフォーマンスも賢明です。

1

上記の答えに基づいてコードを少し修正してみました。バインディングは私にとっては両方の方法で機能しませんでした。以下の内容は、2つの方法でバインドすることができます。

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); 
    } 
関連する問題