2010-08-12 21 views
5

मैं डब्ल्यूपीएफ रिचटेक्स्टबॉक्स का उपयोग कर एक वर्ड प्रोसेसर-टाइप ऐप पर काम कर रहा हूं। मैं SelectionChanged घटना का उपयोग कर रहा है क्या फ़ॉन्ट, फ़ॉन्ट वजन, शैली, आदि निम्नलिखित कोड का उपयोग कर RTB में वर्तमान चयन की है यह पता लगाने की:डब्ल्यूपीएफ रिचटेक्स्टबॉक्स चयन चेंज प्रदर्शन

private void richTextBox_SelectionChanged(object sender, RoutedEventArgs e) 
    { 
     TextSelection selection = richTextBox.Selection; 

     if (selection.GetPropertyValue(FontFamilyProperty) != DependencyProperty.UnsetValue) 
     { 
      //we have a single font in the selection 
      SelectionFontFamily = (FontFamily)selection.GetPropertyValue(FontFamilyProperty); 
     } 
     else 
     { 
      SelectionFontFamily = null; 
     } 

     if (selection.GetPropertyValue(FontWeightProperty) == DependencyProperty.UnsetValue) 
     { 
      SelectionIsBold = false; 
     } 
     else 
     { 
      SelectionIsBold = (FontWeights.Bold == ((FontWeight)selection.GetPropertyValue(FontWeightProperty))); 
     } 

     if (selection.GetPropertyValue(FontStyleProperty) == DependencyProperty.UnsetValue) 
     { 
      SelectionIsItalic = false; 
     } 
     else 
     { 
      SelectionIsItalic = (FontStyles.Italic == ((FontStyle)selection.GetPropertyValue(FontStyleProperty))); 
     } 

     if (selection.GetPropertyValue(Paragraph.TextAlignmentProperty) != DependencyProperty.UnsetValue) 
     { 
      SelectionIsLeftAligned = (TextAlignment)selection.GetPropertyValue(Paragraph.TextAlignmentProperty) == TextAlignment.Left; 
      SelectionIsCenterAligned = (TextAlignment)selection.GetPropertyValue(Paragraph.TextAlignmentProperty) == TextAlignment.Center; 
      SelectionIsRightAligned = (TextAlignment)selection.GetPropertyValue(Paragraph.TextAlignmentProperty) == TextAlignment.Right; 
      SelectionIsJustified = (TextAlignment)selection.GetPropertyValue(Paragraph.TextAlignmentProperty) == TextAlignment.Justify; 
     }    
    } 

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

दुर्भाग्य से, यह प्रदर्शन की कीमत पर काम करता है, जो बड़ी मात्रा में टेक्स्ट चुनते समय गंभीर रूप से प्रभावित होता है। सबकुछ चुनना काफी धीमा है, और फिर चयन को बदलने के लिए Shift + तीर कुंजी जैसे कुछ का उपयोग करना बहुत धीमा है। स्वीकार्य होने के लिए बहुत धीमी है।

क्या मैं कुछ गलत कर रहा हूं? प्रक्रिया में आरटीबी के प्रदर्शन को मारने के बिना आरटीबी में चयनित पाठ के गुणों को प्रतिबिंबित करने के लिए बाध्य नियंत्रण के गुणों को प्रतिबिंबित करने के बारे में कोई सुझाव हैं?

उत्तर

9

आपका दो प्रदर्शन समस्याओं का मुख्य कारण हैं:

  1. आप से आवश्यक
  2. selection.GetPropertyValue() से अधिक बार फोन आप हर बार चयन में परिवर्तन

GetPropertyValue recompute() विधि को दस्तावेज़ में प्रत्येक तत्व के माध्यम से आंतरिक रूप से स्कैन करना चाहिए, जो इसे धीमा कर देता है। ,

private void HandleSelectionChange() 
{ 
    var family = selection.GetPropertyValue(FontFamilyProperty); 
    var weight = selection.GetPropertyValue(FontWeightProperty); 
    var style = selection.GetPropertyValue(FontStyleProperty); 
    var align = selection.GetPropertyValue(Paragraph.TextAlignmentProperty); 

    var unset = DependencyProperty.UnsetValue; 

    SelectionFontFamily = family!=unset ? (FontFamily)family : null; 
    SelectionIsBold = weight!=unset && (FontWeight)weight == FontWeight.Bold; 
    SelectionIsItalic = style!=unset && (FontStyle)style == FontStyle.Italic; 

    SelectionIsLeftAligned = align!=unset && (TextAlignment)align == TextAlignment.Left;  
    SelectionIsCenterAligned = align!=unset && (TextAlignment)align == TextAlignment.Center;  
    SelectionIsRightAligned = align!=unset && (TextAlignment)align == TextAlignment.Right; 
    SelectionIsJustified = align!=unset && (TextAlignment)align == TextAlignment.Justify; 
} 

यह 3x के बारे में तेजी से हो जाएगा, लेकिन यह वास्तव में अंत उपयोगकर्ता के लिए तेज़ महसूस करने के लिए सेटिंग को अपडेट नहीं करते: तो बजाय एक ही तर्क के साथ इसे कई बार बुलाने की, वापसी मान संग्रहीत तुरंत हर बदलाव पर। इसके बजाय, ContextIdle पर अद्यतन:

bool _queuedChange; 

private void richTextBox_SelectionChanged(object sender, RoutedEventArgs e) 
{ 
    if(!_queuedChange) 
    { 
    _queuedChange = true; 
    Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, (Action)(() => 
    { 
     _queuedChange = false; 
     HandleSelectionChange(); 
    })); 
    } 
} 

यह कहता है HandleSelctionChanged() विधि (ऊपर) वास्तव में चयन परिवर्तन को संभालने के लिए है, लेकिन जब तक ContextIdle डिस्पैचर प्राथमिकता कॉल विलंब है और यह भी कोई फर्क नहीं पड़ता कि कितने चयन परिवर्तन की घटनाओं आ केवल एक अद्यतन कतार में।

अतिरिक्त speedups संभव

ऊपर कोड एक भी DispatcherOperation, जिसका अर्थ है आप अभी भी एक "अंतराल" के रूप में लंबे समय के रूप में चार कॉल हो सकता है में सभी चार GetPropertyValue बनाता है। एक अतिरिक्त 4x अंतराल को कम करने के लिए, केवल एक GetPropertyValue प्रति डिस्पैचर ऑपरेशन करें। इसलिए, उदाहरण के लिए, पहला डिस्पैचर ऑपरेशन GetPropertyValue (FontFamilyProperty) को कॉल करेगा, परिणाम को फ़ील्ड में संग्रहीत करेगा, और फ़ॉन्ट वजन प्राप्त करने के लिए अगले डिस्पैचर ऑपरेशन को शेड्यूल करेगा। प्रत्येक बाद के डिस्पैचर ऑपरेशन वही करेंगे।

यदि यह अतिरिक्त गति अभी भी पर्याप्त नहीं है, तो अगला चरण चयन को छोटे टुकड़ों में विभाजित करना होगा, अलग-अलग डिस्पैचरऑपरेशन में प्रत्येक टुकड़े पर GetPropertyValue को कॉल करें, फिर आपके द्वारा प्राप्त परिणामों को गठबंधन करें।

पूर्ण अधिकतम चिकनीता प्राप्त करने के लिए, आप GetPropertyValue (केवल चयन में सामग्री एलीमेंट्स को पुन: सक्रिय करें) के लिए अपना कोड लागू कर सकते हैं जो क्रमशः काम करता है और 100 तत्वों की जांच के बाद लौटाता है।अगली बार जब आप इसे कॉल करेंगे तो यह उस स्थान को उठाएगा जहां से यह छोड़ा गया था। यह DispatcherOperation द्वारा किए गए काम की मात्रा को अलग करके किसी भी समझदार अंतराल को रोकने की आपकी क्षमता की गारंटी देगा।

सहायता थ्रेडिंग?

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

+0

आपके कोड के लिए धन्यवाद, इसने वास्तव में गति को बढ़ाया जैसा आपने कहा था, लेकिन आरटीबी में एक अच्छी मात्रा में टेक्स्ट होने पर यह अभी भी बहुत कम है (15 पेज या उससे भी ज्यादा कहें)। जब आप सभी टेक्स्ट को हाइलाइट करते हैं और पंक्तियों/शब्दों को अचयनित करने के लिए तीर कुंजियों का उपयोग करते हैं, तो यह अभी भी पर्याप्त है कि यह काफी ध्यान देने योग्य है। तो यह बेहतर है, लेकिन अभी भी वहाँ नहीं है। क्या ऐसा कुछ थ्रेड में लगाया जा सकता है? – Scott

+0

मैंने आपको कुछ जवाब देने के लिए अपना जवाब बढ़ा दिया है कि आगे की गति के लिए क्या आवश्यक होगा, और कोई धागा सहायक होगा या नहीं। –

+0

उत्कृष्ट सलाह, धन्यवाद रे। मैं आपको अधिक विस्तार से सुझावों को देखूंगा। – Scott

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