2010-06-15 11 views
7

मैं एक WPF RichTextBox में टेक्स्ट पॉइंटर क्लास के चारों ओर अपना सिर लेने की कोशिश कर रहा हूं।WPF RichTextBox में TextPointer का ट्रैक कैसे रखें?

मैं उनका ट्रैक रखने में सक्षम होना चाहता हूं ताकि मैं टेक्स्ट में क्षेत्रों के साथ जानकारी को जोड़ सकूं।

मैं वर्तमान में एक बहुत ही सरल उदाहरण के साथ काम कर रहा हूं ताकि यह पता चल सके कि क्या हो रहा है। पूर्वावलोकनकेडडाउन घटना में मैं कैरेट की स्थिति संग्रहीत कर रहा हूं और फिर पूर्वावलोकनकेप अप ईवेंट में मैं कैरेट की स्थिति के पहले और बाद के आधार पर एक टेक्स्टरेंज बना रहा हूं।

// The caret position before typing 
private TextPointer caretBefore = null; 

private void rtbTest_PreviewKeyDown(object sender, KeyEventArgs e) 
{ 
    // Store caret position 
    caretBefore = rtbTest.CaretPosition; 
} 

private void rtbTest_PreviewKeyUp(object sender, KeyEventArgs e) 
{ 
    // Get text between before and after caret positions 
    TextRange tr = new TextRange(caretBefore, rtbTest.CaretPosition); 
    MessageBox.Show(tr.Text); 
} 

समस्या यह है कि पाठ है कि मैं पाने खाली है है: यहाँ एक कोड नमूना दिखाता है कि मैं क्या करने की कोशिश कर रहा हूँ। उदाहरण के लिए, यदि मैं 'ए' अक्षर टाइप करता हूं तो मुझे टेक्स्टरेंज में टेक्स्ट "ए" ढूंढने की उम्मीद होगी।

क्या किसी को पता है कि क्या गलत हो रहा है? यह कुछ बहुत आसान हो सकता है लेकिन मैंने दोपहर कहीं भी नहीं बिताया है।

मैं नई WPF तकनीक को गले लगाने की कोशिश कर रहा हूं लेकिन यह पता चलता है कि विशेष रूप से RichTextBox इतना जटिल है कि यह इस तरह की सरल चीजों को भी आसान बनाता है। अगर किसी के पास कोई लिंक है जो टेक्स्ट पॉइंटर को समझाने का अच्छा काम करता है, तो मैं इसकी सराहना करता हूं अगर आप मुझे बता सकते हैं।

उत्तर

19

जब आप फ्लो डॉक्यूमेंट से टेक्स्ट जोड़ते और हटाते हैं, तो सभी टेक्स्टपॉइंटर्स अपनी स्थिति को कई ह्यूरिस्टिक्स पर आधारित करते हैं ताकि उन्हें यथासंभव "स्थान" के करीब रहने के लिए डिज़ाइन किया जा सके।

हटाने के लिए यह आसान है: यदि टेक्स्ट पॉइंटर हटाए गए टेक्स्ट में है, तो यह हटाए गए टेक्स्ट के आस-पास के पात्रों को betweem समाप्त होता है। लेकिन सम्मिलन के लिए यह इतना आसान नहीं है: जब टेक्स्ट या अन्य तत्व फ़्लो डॉक्यूमेंट में एक मौजूदा टेक्स्ट पॉइंटर पर डाले जाते हैं, तो क्या टेक्स्टपॉन्टर डाले गए टेक्स्ट से पहले या बाद में समाप्त होना चाहिए? टेक्स्ट पॉइंटर में "लॉजिकल डायरेक्शन" नामक एक संपत्ति होती है जो इसे नियंत्रित करती है।

आपके मामले में क्या हो रहा है यह है कि आप जिस "देखभाल से पहले" स्थिति को कैप्चर कर रहे हैं वह बिल्कुल टेक्स्टपोजिशन है जहां टाइप किए गए वर्ण डाले जाते हैं, और आपके परीक्षण मामलों में आपका लॉजिकल डायरेक्शन लॉजिकल डायरेक्शन होता है। आगे। इस प्रकार जब चरित्र डाला जाता है, तो आपकी "देखभाल से पहले" के बाद डाला गया चरित्र है, जो टेक्स्टपोजिशन के साथ मेल खाता है जो आपको एक खाली टेक्स्टरेंज देता है।

टेक्स्टपॉइंटर को लॉजिकल डायरेक्शन कैसे दिया जाता है? यदि आप कैरेट स्थिति सेट करने के लिए RichTextBox पर क्लिक करते हैं, तो क्लिक को दो वर्णों के बीच के रूप में व्याख्या किया जाता है। यदि आपके द्वारा क्लिक किया गया वास्तविक बिंदु दूसरे चरित्र पर था, तो लॉजिकल डायरेक्शन फ़ॉरवर्ड पर सेट किया गया है, लेकिन यदि आपके द्वारा क्लिक किया गया वास्तविक बिंदु पहला अक्षर था, तो लॉजिकल डायरेक्शन बैकवर्ड पर सेट होता है।

इस प्रयोग का प्रयास करें:

  1. अपने FONTSIZE = "40" सेट और पाठ "एबीसीडी" निर्माता बी के दाईं ओर
  2. क्लिक करें साथ RichTextBox prepopulate और प्रकार एक "X "बी और सी के बीच लॉजिकल डायरेक्शन बैकवर्ड है, इसलिए आपका" पहले कैरेट "" एक्स "से पहले समाप्त होता है और आपका संदेशबॉक्स" एक्स "दिखाता है।
  3. सी के बाईं ओर क्लिक करें और बी और सी के बीच एक "एक्स" टाइप करें। लॉजिकल डायरेक्शन फॉरवर्ड है, इसलिए "एक्स" के बाद आपका "पहले कैरेट" समाप्त हो गया है और आपका संदेशबॉक्स खाली है।

यह व्यवहार प्रतिद्वंद्वी है: जब आपको पता नहीं है कि लॉजिकल डायरेक्शन मौजूद है, तो आपको लगता है कि बी के दाएं हाथ पर क्लिक करना या सी के बाएं हाथ की ओर आपको बिल्कुल वही देना होगा देखभाल की स्थिति

नोट: क्या चल रहा है कल्पना करने के लिए एक आसान तरीका है अपने MessageBox.Show बाहर आदेश और बजाय एक caretBefore.InsertTextInRun("^");

कैसे आप परिणाम आप की जरूरत को प्राप्त करते है? लॉजिकल डायरेक्शन केवल पढ़ने के लिए है।

caretBefore = new TextRange(caretBefore, caretBefore.DocumentEnd).Start; 

PreviewKeyDown में यह करें: एक तरह से पिछड़ा के LogicalDirection के साथ एक TextPointer के निर्माण के लिए मजबूर करने के TextRange उपयोग करने के लिए है। यदि आप पूर्वावलोकन के लिए प्रतीक्षा करते हैं तो यह पहले से ही बहुत देर हो चुकी है: देखभाल पहले से चली गई है। यह काम करता है क्योंकि जहां तक ​​मैं कह सकता हूं, एक गैर-खाली टेक्स्टरेंज की शुरुआत में हमेशा पीछे की लॉजिकल डायरेक्शन होती है।

एक और विकल्प दस्तावेज़ की शुरुआत से प्रतीक ऑफ़सेट को सहेजना है (ध्यान दें कि यह एक चरित्र ऑफसेट नहीं है!)। इस मामले में आप PreviewKeyDown में ऑफसेट संग्रहीत कर सकती है:

caretBeforeOffset = caretBefore.DocumentStart.OffsetToPosition(caretBefore); 

और एक ही प्रतीक PreviewKeyUp में ऑफसेट करने के लिए caretBefore रीसेट:

caretBefore = caretBefore.DocumentStart.GetPositionAtOffset(caretBeforeOffset, 
                  LogicalDirection.Forward); 

हालांकि यह काम करता है यह आपके TextPointer लिए मजबूर करने के लिए के रूप में के रूप में सामान्य नहीं है बैकवर्ड की लॉजिकल डायरेक्शन: पूर्वावलोकनकिडडाउन और पूर्वावलोकनकेयअप के बीच दस्तावेज़ में पहले से कोई भी टेक्स्ट बदलता है, गलत स्थान खोजने के लिए प्रतीकात्मक ऑफ़सेट गणना का कारण बनता है, जो टेक्स्टपॉइंटर्स को पहले स्थान पर ठीक करने के लिए डिज़ाइन किया गया था।

मुझे दस्तावेज पढ़ने और उनके साथ खेलने के अलावा टेक्स्टपॉइंटर्स के बारे में सीखने के लिए किसी भी अच्छे संसाधन के बारे में पता नहीं है, जो वास्तव में आप पहले से ही कर रहे हैं।

+0

हाय रे, इस तरह के एक सूचनात्मक उत्तर के लिए बहुत बहुत धन्यवाद। यह बहुत सराहना की है और निश्चित रूप से तार्किक दिशाओं के बारे में स्पष्ट चीजों को मेरी मदद करता है - मैंने आपके प्रयोग की कोशिश की। जो मैंने अंततः विचार किया है वह लाइन लाइन से दस्तावेज़ लाइन को संसाधित कर रहा है। मुझे GetLineStartPosition विधि के बारे में पता है, लेकिन अगर आपको पता है कि टेक्स्टपॉइंटर से लाइन के अंत की स्थिति कैसे प्राप्त करें? धन्यवाद, एलन –

+0

आप नियंत्रित कर सकते हैं कि गेटलाइन स्टार्टपॉजिशन आपके द्वारा गुजरने वाली गिनती को बदलकर कैसे चलता है। यदि आप इस काम के बारे में अधिक जानकारी चाहते हैं और लाइन स्थिति के अंत को पाने के लिए इसका उपयोग कैसे करें, तो कृपया यहां एक और प्रश्न पोस्ट करें स्टैक ओवरफ़्लो। यह बताने के लिए पर्याप्त है कि यह एक अलग प्रश्न और उत्तर वारंट करता है। इन टिप्पणियों में स्वरूपण क्षमताओं भी बेहद सीमित है। –

+0

हाय रे, मेरे पास वापस आने के लिए धन्यवाद। मैं टिप्पणियों की सीमाओं की सराहना करता हूं और यहां एक नया प्रश्न पोस्ट कर चुका हूं: http://stackoverflow.com/questions/3060108/using-getlinestartposition-to-get-the-end-of-a-line-in-wpf- richtextbox –

संबंधित मुद्दे