2013-02-13 17 views
8

मैंने अपनी परियोजना में AvalonEdit का उपयोग किया है जो WPF और MVVM पर आधारित है। 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

डब्ल्यूपीएफ बाइंडिंग आपके 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 का उपयोग करके आप पाठ परिवर्तन के दौरान बाइंड्रोपर्टी को बाध्य करने के लिए नहीं प्राप्त कर सकते हैं, इसलिए डैनियल का उत्तर किसी भी तरह से पालन किया जाना चाहिए।

मैं इसे और अधिक अंत सामान्य और निर्भरता मोड के रूप में पाठ का उपयोग किए उपयोगकर्ता के लिए सहज बनाने के लिए थोड़ा बदल किया:

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

मैं जाँच करने के लिए किया था, तो एक ही पाठ से बचने के लिए पहले से ही वहाँ था पूर्ववत स्टैक इंजन अपवाद। प्रदर्शन के अनुसार भी एक अच्छा सौदा है।

1

मैंने मामूली संशोधन के साथ उपरोक्त उत्तरों के आधार पर कोड की कोशिश की, क्योंकि बाध्यकारी मेरे लिए दोनों तरीकों से काम नहीं कर रहा था। नीचे दी गई सामग्री को दो तरीकों से बांधने की अनुमति देनी चाहिए।

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); 
    } 
संबंधित मुद्दे