2010-04-02 13 views
8

Tengo un WPF RichTextBox en el que estoy escribiendo texto y luego analizando todo el texto para procesarlo. Durante este análisis, tengo las posiciones absolutas de los caracteres del inicio y el final de cada palabra.WPF FlowDocument - Posición absoluta del personaje

Me gustaría utilizar estas posiciones de caracteres para aplicar formato a ciertas palabras. Sin embargo, he descubierto que FlowDocument usa instancias TextPointer para marcar posiciones en el documento.

He descubierto que puedo crear un TextRange construyéndolo con punteros de inicio y final. Una vez que tenga el TextRange, puedo aplicar fácilmente el formato al texto que contiene. He estado usando GetPositionAtOffset para obtener un TextPointer para mi desplazamiento de caracteres, pero sospecho que su desplazamiento es diferente del mío porque el texto seleccionado está en una posición ligeramente diferente de lo que esperaba.

Mi pregunta es, ¿cómo puedo convertir con precisión una posición de carácter absoluta en un TextPointer?

+1

+1, tengo este problema exacto - hacer análisis personalizada y los aspectos más destacados están desplazados mal :-) – Cameron

Respuesta

5

No encontré una forma confiable de convertir las posiciones absolutas de los caracteres en instancias de TextPosition.

Mi solución alternativa fue modificar el análisis original para trabajar en ejecuciones individuales en lugar de capturar todo el texto de RichTextBox. Trabajar con posiciones de caracteres que son relativas a una instancia de Ejecución específica ha demostrado ser confiable para mí. Creo que me ha ayudado a mover mi mentalidad hacia la forma de pensar de WPF.

Tomé el siguiente enfoque para navegar carreras en la FlowDocument (inspirado en 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

Tuve un problema similar exacto, descubrí que hay un error en RichTextBox porque no cuenta "nuevos caracteres de línea - \ r \ n", así que a medida que aumentan sus números de línea, encontrará que su desplazamiento es posicionado incorrectamente por número de línea, y resolví mis problemas al compensar el número de línea del desplazamiento.

+0

Hola Akash, Gracias por su respuesta. Mi experiencia es que ESTÁ contando mis nuevos caracteres de línea, pero he notado que las líneas completamente en blanco "" están causando que FlowDocument tenga 2 caracteres por delante de mis compensaciones (acumulando después de cada salto de línea). Alan –

3

también he tenido este problema y ha terminado con el siguiente método de extensión RichTextBox. ¡En mi contexto, funciona sin problemas!

/// <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; 
} 
Cuestiones relacionadas