rich example ejemplo c# wpf richtextbox

example - richtextbox c# ejemplo



Seleccionar rango de texto en WPF RichTextBox(FlowDocument) mediante programaciĆ³n (8)

Incidentalmente (y esto puede ser académico para todos, excepto para mí), si establece FocusManager.IsFocusScope = "True" en el contenedor de RichTextBox, una cuadrícula, por ejemplo,

<Grid FocusManager.IsFocusScope="True">...</Grid>

entonces debería poder usar el método Colorize de Johan Danforth sin las dos invocaciones de ApplyPropertyValue, y RichTextBox debería usar la selección predeterminada Fondo y Primer plano para resaltar la selección.

private void Colorize(int offset, int length, Color color) { var textRange = MyRichTextBox.Selection; var start = MyRichTextBox.Document.ContentStart; var startPos = GetPoint(start, offset); var endPos = GetPoint(start, offset + length); textRange.Select(startPos, endPos); }

No lo he probado con el RichTextBox, pero funciona bastante bien cuando se crea una plantilla para encontrar un TextBox en un FlowDocumentReader. Sólo para asegurarse de que también puede establecer

<RichTextBox FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}">...</RichTextBox>

para asegurar que RichTextBox tenga foco dentro de su alcance de enfoque.

La desventaja de esto, por supuesto, es que si el usuario hace clic o realiza una selección dentro de RichTextBox, su selección desaparece.

Tengo este WPF RichTextBox y quiero seleccionar un rango dado de letras / palabras mediante programación y resaltarlo. He intentado esto, pero no funciona, probablemente porque no estoy teniendo en cuenta algunas etiquetas ocultas de FlowDocument o similares. Por ejemplo, quiero seleccionar las letras 3-8 pero se selecciona 2-6):

var start = MyRichTextBox.Document.ContentStart; var startPos = start.GetPositionAtOffset(3); var endPos = start.GetPositionAtOffset(8); var textRange = new TextRange(startPos,endPos); textRange.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Blue)); textRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);

Me he dado cuenta de que el manejo de RichTextBox es un poco más complicado de lo que pensaba :)

Actualización: obtuve algunas respuestas en los foros de MSDN: este hilo donde "dekurver" seid:

Las compensaciones que está especificando no son compensaciones de caracteres sino compensaciones de símbolos. Lo que debe hacer es obtener un TextPointer que sepa que está adyacente al texto, luego puede agregar compensaciones de caracteres.

Y "LesterLobo" dijo:

Tendrá que recorrer los párrafos y las líneas para encontrar el Siguiente y luego sus compensaciones en un bucle para solicitar todas las apariencias del texto específico. tenga en cuenta que cuando edite el texto se moverá, pero el resaltado no se moverá, ya que está asociado al desplazamiento, no al texto. Sin embargo, podría crear una ejecución personalizada y resaltarla ...

Todavía me ENCANTARÍA ver un código de ejemplo para esto si alguien conoce su camino alrededor de FlowDocuments ...

EDITAR Tengo una versión del código de Kratz VB funcionando, se parece a esto:

private static TextPointer GetPoint(TextPointer start, int x) { var ret = start; var i = 0; while (i < x && ret != null) { if (ret.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.Text || ret.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.None) i++; if (ret.GetPositionAtOffset(1, LogicalDirection.Forward) == null) return ret; ret = ret.GetPositionAtOffset(1, LogicalDirection.Forward); } return ret; }

Y lo uso así:

Colorize(item.Offset, item.Text.Length, Colors.Blue); private void Colorize(int offset, int length, Color color) { var textRange = MyRichTextBox.Selection; var start = MyRichTextBox.Document.ContentStart; var startPos = GetPoint(start, offset); var endPos = GetPoint(start, offset + length); textRange.Select(startPos, endPos); textRange.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(color)); textRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold); }


Intenté usar la solución publicada por KratzVB pero descubrí que estaba ignorando las nuevas líneas. Si desea contar los símbolos / ry / n, este código debería funcionar:

private static TextPointer GetPoint(TextPointer start, int x) { var ret = start; var i = 0; while (ret != null) { string stringSoFar = new TextRange(ret, ret.GetPositionAtOffset(i, LogicalDirection.Forward)).Text; if (stringSoFar.Length == x) break; i++; if (ret.GetPositionAtOffset(i, LogicalDirection.Forward) == null) return ret.GetPositionAtOffset(i-1, LogicalDirection.Forward) } ret=ret.GetPositionAtOffset(i, LogicalDirection.Forward); return ret; }


Mi versión basada en la versión de cave_dweller.

private static TextPointer GetPositionAtCharOffset(TextPointer start, int numbertOfChars) { var offset = start; int i = 0; string stringSoFar=""; while (stringSoFar.Length < numbertOfChars) { i++; TextPointer offsetCandidate = start.GetPositionAtOffset( i, LogicalDirection.Forward); if (offsetCandidate == null) return offset; // ups.. we are to far offset = offsetCandidate; stringSoFar = new TextRange(start, offset).Text; } return offset; }

Para omitir algunos caracteres agregue este código dentro del bucle:

stringSoFar = stringSoFar.Replace("/r/n", "") .Replace(" ", "")

En lugar de esto (lento):

var startPos = GetPoint(start, offset); var endPos = GetPoint(start, offset + length);

Debes hacer esto (más rápido)

var startPos = GetPoint(start, offset); var endPos = GetPoint(startPos, length);

O crea un método separado para obtener TextRange:

private static TextRange GetTextRange(TextPointer start, int startIndex, int length) { var rangeStart = GetPositionAtCharOffset(start, startIndex); var rangeEnd = GetPositionAtCharOffset(rangeStart, length); return new TextRange(rangeStart, rangeEnd); }

Ahora puede formatear texto sin Select() ing:

var range = GetTextRange(Document.ContentStart, 3, 8); range.ApplyPropertyValue( TextElement.BackgroundProperty, new SolidColorBrush(Colors.Aquamarine));


No se pudo encontrar una solución con una solución de rendimiento aceptable para este problema durante mucho tiempo. La siguiente muestra funciona en mi caso con el mayor rendimiento. Espero que ayude a alguien también.

TextPointer startPos = rtb.Document.ContentStart.GetPositionAtOffset(searchWordIndex, LogicalDirection.Forward); startPos = startPos.CorrectPosition(searchWord, FindDialog.IsCaseSensitive); if (startPos != null) { TextPointer endPos = startPos.GetPositionAtOffset(textLength, LogicalDirection.Forward); if (endPos != null) { rtb.Selection.Select(startPos, endPos); } } public static TextPointer CorrectPosition(this TextPointer position, string word, bool caseSensitive) { TextPointer start = null; while (position != null) { if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text) { string textRun = position.GetTextInRun(LogicalDirection.Forward); int indexInRun = textRun.IndexOf(word, caseSensitive ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase); if (indexInRun >= 0) { start = position.GetPositionAtOffset(indexInRun); break; } } position = position.GetNextContextPosition(LogicalDirection.Forward); } return start; }


Trata eso :

var textRange = MyRichTextBox.Selection; var start = MyRichTextBox.Document.ContentStart; var startPos = start.GetPositionAtOffset(3); var endPos = start.GetPositionAtOffset(8); textRange.Select(startPos, endPos); textRange.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Blue)); textRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);


private void SelectText(int start, int length) { TextRange textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd); TextPointer pointerStart = textRange.Start.GetPositionAtOffset(start, LogicalDirection.Forward); TextPointer pointerEnd = textRange.Start.GetPositionAtOffset(start + length, LogicalDirection.Backward); richTextBox.Selection.Select(pointerStart, pointerEnd); }


private TextPointer GetPoint(TextPointer start, int pos) { var ret = start; int i = 0; while (i < pos) { if (ret.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text) i++; if (ret.GetPositionAtOffset(1, LogicalDirection.Forward) == null) return ret; ret = ret.GetPositionAtOffset(1, LogicalDirection.Forward); } return ret; }


Public Function GoToPoint(ByVal start As TextPointer, ByVal x As Integer) As TextPointer Dim out As TextPointer = start Dim i As Integer = 0 Do While i < x If out.GetPointerContext(LogicalDirection.Backward) = TextPointerContext.Text Or _ out.GetPointerContext(LogicalDirection.Backward) = TextPointerContext.None Then i += 1 End If If out.GetPositionAtOffset(1, LogicalDirection.Forward) Is Nothing Then Return out Else out = out.GetPositionAtOffset(1, LogicalDirection.Forward) End If Loop Return out End Function

Intente esto, esto debería devolver un puntero de texto para la compensación de caracteres dada. (Lo siento, está en VB, pero eso es en lo que estoy trabajando ...)