动态更改 wpf 文本块中多个 spans/regions 上的文本装饰
dynamically change text decorations on multiple spans/regions in a wpf textblock
我正在尝试设计一个应用程序,如果该字符串中包含另外 1 或 2 个字符串,则删除该字符串中的某些字符。
到目前为止,我似乎可以让前导子字符串相当可靠地完成它的工作,但第二个子字符串似乎总是产生不可预测的结果,有人能帮忙吗? (c# 或 vb 都可以)
它适用于主(第一个)过滤器但不适用于子(第二个)过滤器的屏幕截图示例:
代码如下:
Public Function FormatFilteredName(mainFilter As String, subFilter As String) As TextBlock
Dim tbNew As New TextBlock(New Run(FullFileName))
tbNew.Text = FullFileName
tbNew.FontSize = FONT_SIZE
If Not String.IsNullOrEmpty(FullFileName) Then
If Not String.IsNullOrEmpty(mainFilter) Then
GetFilterSpan(mainFilter, tbNew)
End If
If Not String.IsNullOrEmpty(subFilter) Then
GetFilterSpan(subFilter, tbNew)
End If
End If
Return tbNew
Private Function GetFilterSpan(filter As String, ByVal tbNew As TextBlock) As Span
Dim offset As Integer = tbNew.Text.ToLower().IndexOf(filter.ToLower()) + 1
Try
If offset > -1 Then
Dim tpStart As TextPointer
tpStart = tbNew.ContentStart.GetPositionAtOffset(offset)
Dim tpEnd As TextPointer
tpEnd = tbNew.ContentStart.GetPositionAtOffset(offset + filter.Length)
If Not tpStart Is Nothing And Not tpEnd Is Nothing Then
Dim result As New Span(tpStart, tpEnd)
result = ApplySpanStrikeOutStyle(result)
Return result
End If
End If
Catch ex As Exception
Return Nothing
End Try
如果您 运行 您的代码在 tbNew.ContentEnd.Offset 上设置了手表,您将看到应用删除线时值发生变化。这说明了为什么使用
Dim offset As Integer = tbNew.Text.ToLower().IndexOf(filter.ToLower()) + 1
不准确 - 您是从纯文本获取 IndexOf,然后将该偏移量应用于应用了文本装饰的内容。
根据答案 here,这应该可以帮助您。
Public Function FormatFilteredName(mainFilter As String, subFilter As String) As TextBlock
' Dim tbNew As New TextBlock(New Run("111xxJoe Blogs09"))
' tbNew.Text = "111xxJoe Blogs09"
' tbNew.FontSize = 10
If Not String.IsNullOrEmpty(tbNew.Text) Then
If Not String.IsNullOrEmpty(mainFilter) Then
Dim mainFilterRange As TextRange = FindWordFromPosition(tbNew.ContentStart, mainFilter)
If mainFilterRange IsNot Nothing Then
ApplyStrikeOutStyle(mainFilterRange)
End If
End If
If Not String.IsNullOrEmpty(subFilter) Then
Dim subFilterRange As TextRange = FindWordFromPosition(tbNew.ContentStart, subFilter)
If subFilterRange IsNot Nothing Then
ApplyStrikeOutStyle(subFilterRange)
End If
End If
End If
Return tbNew
End Function
Private Function ApplyStrikeOutStyle(result As TextRange) As TextRange
result.ApplyPropertyValue(Inline.TextDecorationsProperty,
TextDecorations.Strikethrough)
Return result
End Function
Private Function FindWordFromPosition(position As TextPointer, word As String) As TextRange
While position IsNot Nothing
If position.GetPointerContext(LogicalDirection.Forward) = TextPointerContext.Text Then
Dim textRun As String = position.GetTextInRun(LogicalDirection.Forward)
' Find the starting index of any substring that matches "word".
Dim indexInRun As Integer = textRun.IndexOf(word)
If indexInRun >= 0 Then
Dim start As TextPointer = position.GetPositionAtOffset(indexInRun)
Dim [end] As TextPointer = start.GetPositionAtOffset(word.Length)
Return New TextRange(start, [end])
End If
End If
position = position.GetNextContextPosition(LogicalDirection.Forward)
End While
' position will be null if "word" is not found.
Return Nothing
End Function
我正在尝试设计一个应用程序,如果该字符串中包含另外 1 或 2 个字符串,则删除该字符串中的某些字符。
到目前为止,我似乎可以让前导子字符串相当可靠地完成它的工作,但第二个子字符串似乎总是产生不可预测的结果,有人能帮忙吗? (c# 或 vb 都可以)
它适用于主(第一个)过滤器但不适用于子(第二个)过滤器的屏幕截图示例:
代码如下:
Public Function FormatFilteredName(mainFilter As String, subFilter As String) As TextBlock
Dim tbNew As New TextBlock(New Run(FullFileName))
tbNew.Text = FullFileName
tbNew.FontSize = FONT_SIZE
If Not String.IsNullOrEmpty(FullFileName) Then
If Not String.IsNullOrEmpty(mainFilter) Then
GetFilterSpan(mainFilter, tbNew)
End If
If Not String.IsNullOrEmpty(subFilter) Then
GetFilterSpan(subFilter, tbNew)
End If
End If
Return tbNew
Private Function GetFilterSpan(filter As String, ByVal tbNew As TextBlock) As Span
Dim offset As Integer = tbNew.Text.ToLower().IndexOf(filter.ToLower()) + 1
Try
If offset > -1 Then
Dim tpStart As TextPointer
tpStart = tbNew.ContentStart.GetPositionAtOffset(offset)
Dim tpEnd As TextPointer
tpEnd = tbNew.ContentStart.GetPositionAtOffset(offset + filter.Length)
If Not tpStart Is Nothing And Not tpEnd Is Nothing Then
Dim result As New Span(tpStart, tpEnd)
result = ApplySpanStrikeOutStyle(result)
Return result
End If
End If
Catch ex As Exception
Return Nothing
End Try
如果您 运行 您的代码在 tbNew.ContentEnd.Offset 上设置了手表,您将看到应用删除线时值发生变化。这说明了为什么使用
Dim offset As Integer = tbNew.Text.ToLower().IndexOf(filter.ToLower()) + 1
不准确 - 您是从纯文本获取 IndexOf,然后将该偏移量应用于应用了文本装饰的内容。
根据答案 here,这应该可以帮助您。
Public Function FormatFilteredName(mainFilter As String, subFilter As String) As TextBlock
' Dim tbNew As New TextBlock(New Run("111xxJoe Blogs09"))
' tbNew.Text = "111xxJoe Blogs09"
' tbNew.FontSize = 10
If Not String.IsNullOrEmpty(tbNew.Text) Then
If Not String.IsNullOrEmpty(mainFilter) Then
Dim mainFilterRange As TextRange = FindWordFromPosition(tbNew.ContentStart, mainFilter)
If mainFilterRange IsNot Nothing Then
ApplyStrikeOutStyle(mainFilterRange)
End If
End If
If Not String.IsNullOrEmpty(subFilter) Then
Dim subFilterRange As TextRange = FindWordFromPosition(tbNew.ContentStart, subFilter)
If subFilterRange IsNot Nothing Then
ApplyStrikeOutStyle(subFilterRange)
End If
End If
End If
Return tbNew
End Function
Private Function ApplyStrikeOutStyle(result As TextRange) As TextRange
result.ApplyPropertyValue(Inline.TextDecorationsProperty,
TextDecorations.Strikethrough)
Return result
End Function
Private Function FindWordFromPosition(position As TextPointer, word As String) As TextRange
While position IsNot Nothing
If position.GetPointerContext(LogicalDirection.Forward) = TextPointerContext.Text Then
Dim textRun As String = position.GetTextInRun(LogicalDirection.Forward)
' Find the starting index of any substring that matches "word".
Dim indexInRun As Integer = textRun.IndexOf(word)
If indexInRun >= 0 Then
Dim start As TextPointer = position.GetPositionAtOffset(indexInRun)
Dim [end] As TextPointer = start.GetPositionAtOffset(word.Length)
Return New TextRange(start, [end])
End If
End If
position = position.GetNextContextPosition(LogicalDirection.Forward)
End While
' position will be null if "word" is not found.
Return Nothing
End Function