2010-04-02 12 views
8

Possiedo un RichTextBox WPF in cui sto digitando del testo e quindi analizzando l'intero testo su cui eseguire l'elaborazione. Durante questa analisi, ho le posizioni assolute dei caratteri all'inizio e alla fine di ogni parola.WPF FlowDocument - Posizione carattere assoluto

Vorrei utilizzare queste posizioni di carattere per applicare la formattazione a determinate parole. Tuttavia, ho scoperto che FlowDocument utilizza istanze di TextPointer per contrassegnare le posizioni nel documento.

Ho scoperto che posso creare un TextRange costruendolo con i puntatori iniziale e finale. Una volta che ho il TextRange posso facilmente applicare la formattazione al testo al suo interno. Ho utilizzato GetPositionAtOffset per ottenere un oggetto TextPointer per il mio carattere offset, ma sospetto che il suo offset sia diverso dal mio perché il testo selezionato si trova in una posizione leggermente diversa da quella che mi aspetto.

La mia domanda è, come posso convertire con precisione una posizione di carattere assoluto in un oggetto TextPointer?

+1

+1, ho questo problema esatto - fare analisi personalizzate e le luci sono compensate sbagliato :-) – Cameron

risposta

5

Non ho trovato un metodo affidabile per convertire posizioni di caratteri assoluti in istanze di TextPosition.

La mia soluzione alternativa era quella di modificare l'analisi originale per lavorare su singole corse piuttosto che catturare l'intero testo di RichTextBox. Lavorare con posizioni di carattere relative ad una specifica istanza di esecuzione si è dimostrata affidabile per me. Penso che spostare la mia mentalità più verso il modo di pensare del WPF abbia aiutato.

ho preso il seguente approccio per la navigazione viene eseguito in FlowDocument (ispirata http://blogs.msdn.com/prajakta/archive/2006/10/12/customize-richtextbox-to-allow-only-plain-text-input.aspx):

// Get starting pointer 
TextPointer navigator = flowDocument.ContentStart; 

// While we are not at end of document 
while (navigator.CompareTo(flowDocument.ContentEnd) < 0) 
{ 
    // Get text pointer context 
    TextPointerContext context = navigator.GetPointerContext(LogicalDirection.Backward); 

    // Get parent as run 
    Run run = navigator.Parent as Run; 

    // If start of text element within run 
    if (context == TextPointerContext.ElementStart && run != null) 
    { 
     // Get text of run 
     string runText = run.Text; 

     // ToDo: Parse run text 
    } 

    // Get next text pointer 
    navigator = navigator.GetNextContextPosition(LogicalDirection.Forward); 
} 
1

Avevo esattamente un problema simile, ho scoperto che c'è un bug in RichTextBox perché non conta "caratteri di nuova riga - \ r \ n", così come i numeri di linea aumentano, scoprirai che il tuo offset è posizionato in modo errato per il conteggio dei numeri di riga, e avevo risolto i miei problemi compensando il numero di linea dall'offset.

+0

Hi Akash, Grazie per la risposta. La mia esperienza è che sta contando i miei caratteri di nuova riga ma ho notato che linee completamente vuote "" stanno causando il FlowDocument di 2 caratteri prima dei miei offset (cumulativo dopo ogni interruzione di riga). Alan –

3

ho avuto anche questo problema e ha finito con il seguente metodo di estensione RichTextBox. Nel mio contesto funziona perfettamente!

/// <summary> 
/// Gets the text pointer at the given character offset. 
/// Each line break will count as 2 chars. 
/// </summary> 
/// <param name="richTextBox">The rich text box.</param> 
/// <param name="offset">The offset.</param> 
/// <returns>The TextPointer at the given character offset</returns> 
public static TextPointer GetTextPointerAtOffset(this RichTextBox richTextBox, int offset) 
{ 
    var navigator = richTextBox.Document.ContentStart; 
    int cnt = 0; 

    while (navigator.CompareTo(richTextBox.Document.ContentEnd) < 0) 
    { 
     switch (navigator.GetPointerContext(LogicalDirection.Forward)) 
     { 
      case TextPointerContext.ElementStart: 
       break; 
      case TextPointerContext.ElementEnd: 
       if (navigator.GetAdjacentElement(LogicalDirection.Forward) is Paragraph) 
        cnt += 2; 
       break; 
      case TextPointerContext.EmbeddedElement: 
       // TODO: Find out what to do here? 
       cnt++; 
       break; 
      case TextPointerContext.Text: 
       int runLength = navigator.GetTextRunLength(LogicalDirection.Forward); 

       if (runLength > 0 && runLength + cnt < offset) 
       { 
        cnt += runLength; 
        navigator = navigator.GetPositionAtOffset(runLength); 
        if (cnt > offset) 
         break; 
        continue; 
       } 
       cnt++; 
       break; 
     } 

     if (cnt > offset) 
      break; 

     navigator = navigator.GetPositionAtOffset(1, LogicalDirection.Forward); 

    } // End while. 

    return navigator; 
} 
Problemi correlati