我设置了一个 WPF 文本块,其属性 TextWrapping="Wrap"。
当我在开头传递一个带有制表符(在我的例子中为 vbTab)的长字符串时,我希望换行能够遵循这一点并保持字符串的换行部分缩进。 例如,代替:
[vbTab]这真的很长
并包裹
我想要
[vbTab]这真的很长
[vbTab]并包裹
并且非常适合多个选项卡等。
[编辑 - 其他详细信息]
因为文本块的大小可变,并且包含具有不同缩进量的多行文本,所以我不能只留边距或手动拆分字符串并添加制表符。
本质上我想要的是将文本行视为段落,在换行时保持缩进。
根据你的想法,我能够想出这个解决方案
我会将每行开头的所有制表符转换为 0.5 英寸边距,并在段落中添加相同的文本,并将计算出的边距应用于相同的内容
TextBlock 不可行,因为它对于基本文本内联(如运行粗体、内联 ui 容器等)很有用。在 TextBlock 中添加段落更加复杂,因此我基于 FlowDocument 制定了解决方案。
结果
下面的示例使用
FlowDocumentScrollViewer
或 RichTextBox
或 FlowDocumentReader
或普通 FlowDocument
演示了相同的效果
我已经使用附加属性创建了解决方案,因此您可以将其附加到任何提到的属性,甚至为文档添加您自己的主机。您只需将
IndentationProvider.Text
设置为所需的主机即可。
XAML
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:l="clr-namespace:PreservingIndentationDemo"
Title="MainWindow"
Height="350"
Width="525">
<Window.Resources>
<sys:String x:Key="longString"
xml:space="preserve">	this is really long and wrapped
		another line this is also really long and wrapped
	one more line this is also really long and wrapped
another line this is also really long and wrapped
		another line this is also really long and wrapped
</sys:String>
</Window.Resources>
<Grid>
<FlowDocumentScrollViewer l:IndentationProvider.Text="{StaticResource longString}" />
<!--<RichTextBox l:TextToParaHelper.Text="{StaticResource longString}" IsReadOnly="True"/>-->
<!--<FlowDocumentReader l:TextToParaHelper.Text="{StaticResource longString}" />-->
<!--<FlowDocument l:TextToParaHelper.Text="{StaticResource longString}" />-->
</Grid>
</Window>
	
指制表符
缩进提供者
Class IndentationProvider
Public Shared Function GetText(obj As DependencyObject) As String
Return DirectCast(obj.GetValue(TextProperty), String)
End Function
Public Shared Sub SetText(obj As DependencyObject, value As String)
obj.SetValue(TextProperty, value)
End Sub
' Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
Public Shared ReadOnly TextProperty As DependencyProperty = DependencyProperty.RegisterAttached("Text", GetType(String), GetType(IndentationProvider), New PropertyMetadata(Nothing, AddressOf OnTextChanged))
Private Shared Sub OnTextChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
Dim blocks As BlockCollection = Nothing
Dim rtb As RichTextBox = TryCast(d, RichTextBox)
If rtb IsNot Nothing Then
rtb.Document.Blocks.Clear()
blocks = rtb.Document.Blocks
End If
If blocks Is Nothing Then
Dim fd As FlowDocument = TryCast(d, FlowDocument)
If fd IsNot Nothing Then
fd.Blocks.Clear()
blocks = fd.Blocks
End If
End If
If blocks Is Nothing Then
Dim fdr As FlowDocumentReader = TryCast(d, FlowDocumentReader)
If fdr IsNot Nothing Then
fdr.Document = New FlowDocument()
blocks = fdr.Document.Blocks
End If
End If
If blocks Is Nothing Then
Dim fdr As FlowDocumentScrollViewer = TryCast(d, FlowDocumentScrollViewer)
If fdr IsNot Nothing Then
fdr.Document = New FlowDocument()
blocks = fdr.Document.Blocks
End If
End If
Dim newValue As String = TryCast(e.NewValue, String)
If Not String.IsNullOrWhiteSpace(newValue) Then
For Each line As String In newValue.Split(ControlChars.Lf)
Dim leftMargin As Double = 0
Dim newLine As String = line
While newLine.Length > 0 AndAlso newLine(0) = ControlChars.Tab
leftMargin += 0.5
newLine = newLine.Remove(0, 1)
End While
Dim marginInch As String = leftMargin & "in"
Dim marginDip As Double = CDbl(New LengthConverter().ConvertFromString(marginInch))
Dim para As New Paragraph(New Run(newLine)) With {.Margin = New Thickness(marginDip, 0, 0, 0)}
blocks.Add(para)
Next
End If
End Sub
End Class
演示
尝试演示项目