2013-07-25 15 views
9

Dostaję słabe wyniki podczas formatowania tekstu w RTB:Powolne formatowania RichTextBox

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition/> 
    </Grid.RowDefinitions> 
    <StackPanel Orientation="Horizontal"> 
     <Button Click="ApplyFormatClick">ApplyFormat</Button> 
     <TextBlock x:Name="Time"/> 
    </StackPanel> 

    <RichTextBox x:Name="Rtb" Grid.Row="1"> 
     <RichTextBox.Document> 
      <FlowDocument> 
       <Paragraph> 
        <Run> 
         Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum 
        </Run> 
       </Paragraph> 
      </FlowDocument> 
     </RichTextBox.Document> 
    </RichTextBox> 
</Grid> 

Kod tyle:

private readonly SolidColorBrush _blueBrush = Brushes.Blue; 
private void ApplyFormatClick(object sender, RoutedEventArgs e) 
{ 
    Stopwatch stopwatch = Stopwatch.StartNew(); 
    FlowDocument doc = Rtb.Document; 
    TextRange range = new TextRange(doc.ContentStart, doc.ContentEnd); 
    range.ClearAllProperties(); 
    int i = 0; 
    while (true) 
    { 
     TextPointer p1 = range.Start.GetPositionAtOffset(i); 
     i++; 
     TextPointer p2 = range.Start.GetPositionAtOffset(i); 
     if (p2 == null) 
      break; 
     TextRange tempRange = new TextRange(p1, p2); 
     tempRange.ApplyPropertyValue(TextElement.ForegroundProperty, _blueBrush); 
     tempRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold); 
     i++; 
    } 
    Time.Text = "Formatting took: " + stopwatch.ElapsedMilliseconds + " ms, number of characters: " + range.Text.Length; 
} 

Stosowanie formatowania przejmuje drugi i kiedy profilowanie jej sprawców to:

tempRange.ApplyPropertyValue(TextElement.ForegroundProperty, _blueBrush); 
tempRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold); 

Wyniki profilera są dla mnie dość nieprzejrzyste.

Nigdy wcześniej nie używałam FlowDocument i RichTextBox, więc prawdopodobnie robię to bardzo źle.

Wynik końcowy ma być podobny do VS find replace, który podkreśli dopasowania w tekście na podstawie edytowalnego regex.

Co można zrobić inaczej, aby przyspieszyć? (Sample on Github)

Odpowiedz

8

Propozycja będzie ręcznie konstruować FlowDocument z nowym formatowania (you can check the MSDN Magazine August 2007: WPF Flexible Content Display With Flow Documents, lub ostatnim artykule MSDN Flow Document Overview), co zwiększy wydajność gwałtownie, np używać przykład jeśli zrobić to ręcznie jak poniżej, na moim komputerze będzie uzyskać wynik w 52 ms, gdzie, jak za pomocą ApplyPropertyValue odbędą 1266 ms:

private readonly SolidColorBrush _blueBrush = Brushes.Blue; 

private void ApplyFormatClick(object sender, RoutedEventArgs e) 
{ 
    Stopwatch stopwatch = Stopwatch.StartNew(); 
    FlowDocument doc = Rtb.Document; 
    TextRange range = new TextRange(doc.ContentStart, doc.ContentEnd); 
    Paragraph para = new Paragraph(); 
    string rangetem = range.Text; 
    range.ClearAllProperties(); 

    for(int i=0; i<rangetem.Count();i+=2) 
    { 
     Span s = new Span() { Foreground = _blueBrush }; 
     Bold b = new Bold(); 
     s.Inlines.Add(rangetem[i].ToString()); 
     b.Inlines.Add(s); 
     para.Inlines.Add(b); 
     if(i+1<rangetem.Count()) 
     { 
      para.Inlines.Add(rangetem[i + 1].ToString()); 
     } 
    } 
    doc.Blocks.Clear(); 
    doc.Blocks.Add(para); 

    Time.Text = "Formatting took: " + stopwatch.ElapsedMilliseconds + " ms, number of characters: " + range.Text.Length; 
} 
+0

Tak dramatycznej Impro w rzeczywistości, do 38 ms teraz na śmietniku. –

+0

@Bolu Właśnie uratowałeś moje życie. Miałem fragment kodu z 'ApplyPropertyValue', który trwał do 5 sekund. Dzięki twojemu rozwiązaniu jest superszybki. Dziękuję bardzo. Czy wiesz, dlaczego występują problemy z wydajnością tej funkcji? – Chostakovitch

+0

Link wskazuje tylko na przegląd problemów z MSDN. – Lennart

5

Jeśli powrotem funkcjonalność nie jest potrzebna z RichTextBox można wycisnąć nieco wyższą wydajność przez ustawienie IsUndoEnabled do fałszywego

<RichTextBox IsUndoEnabled="False"> 
1

można znacznie poprawić wydajność formatowanie tekstu przy użyciu następujących metod:

rtb.BeginChange(); 

/// Your formating logic 

rtb.EndChange();