我无法让 Silverlight 2.0 完全按照我想要的方式布置文本。我想要带有换行符和嵌入链接的文本,以及换行,例如网页中的 HTML 文本。
这是我最接近的:
<UserControl x:Class="FlowPanelTest.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"
Width="250" Height="300">
<Border BorderBrush="Black" BorderThickness="2" >
<Controls:WrapPanel>
<TextBlock x:Name="tb1" TextWrapping="Wrap">Short text. </TextBlock>
<TextBlock x:Name="tb2" TextWrapping="Wrap">A bit of text. </TextBlock>
<TextBlock x:Name="tb3" TextWrapping="Wrap">About half of a line of text.</TextBlock>
<TextBlock x:Name="tb4" TextWrapping="Wrap">More than half a line of longer text.</TextBlock>
<TextBlock x:Name="tb5" TextWrapping="Wrap">More than one line of text, so it will wrap onto the following line.</TextBlock>
</Controls:WrapPanel>
</Border>
</UserControl>
但问题是,尽管文本块 tb1 和 tb2 将进入同一行,因为它们完全有足够的空间,但 tb3 之后的文本块不会与前一个块在同一行开始,即使它会换行到下一行。
我希望每个文本块从前一个文本块的结尾处开始,在同一行。我想在某些文本上放置单击事件处理程序。我也想要分段。本质上,我正在尝试解决 Silverlight 2.0 的 XAML 子集中缺少 FlowDocument 和 Hyperlink 控件的问题。
要回答答案中提出的问题:
为什么不对不可点击的文本使用运行?如果我只在可点击的文本上使用单独的 TextBlocks,那么这些文本位仍然会受到上述换行问题的影响。链接之前的 TextBlock 和之后的 TextBlock。基本上都是。看起来我没有很多机会在同一个 TextBlock 中进行多次运行。
用正则表达式和循环将链接与其他文本分开根本不是问题,问题在于显示布局。
为什么不将每个单词放在 WrapPanel 中的单个 TextBlock 中除了是一个丑陋的 hack 之外,这与换行符根本不兼容 - 布局不正确。
它还会使链接文本的下划线样式变为虚线。
这是一个示例,每个单词都在其自己的 TextBlock 中。尝试运行它,请注意,换行符根本没有显示在正确的位置。
<UserControl x:Class="SilverlightApplication2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"
Width="300" Height="300">
<Controls:WrapPanel>
<TextBlock TextWrapping="Wrap">Short1 </TextBlock>
<TextBlock TextWrapping="Wrap">Longer1 </TextBlock>
<TextBlock TextWrapping="Wrap">Longerest1 </TextBlock>
<TextBlock TextWrapping="Wrap">
<Run>Break</Run>
<LineBreak></LineBreak>
</TextBlock>
<TextBlock TextWrapping="Wrap">Short2</TextBlock>
<TextBlock TextWrapping="Wrap">Longer2</TextBlock>
<TextBlock TextWrapping="Wrap">Longerest2</TextBlock>
<TextBlock TextWrapping="Wrap">Short3</TextBlock>
<TextBlock TextWrapping="Wrap">Longer3</TextBlock>
<TextBlock TextWrapping="Wrap">Longerest3</TextBlock>
</Controls:WrapPanel>
</UserControl>
LinkLabelControl与这里和这里一样怎么样。它与上述方法具有相同的问题,因为它几乎相同。尝试运行示例,并使链接文本越来越长,直到它换行。请注意,链接从新行开始,它不应该。使链接文本更长,使链接文本比一行长。请注意,它根本不包裹,它会切断。此控件也不处理换行符和分段符。
为什么不将文本全部放在运行中,检测对包含 TextBlock 的点击并确定单击了哪个运行 运行没有鼠标事件,但包含 TextBlock 有。我找不到检查跑步是否在鼠标下方(Silverlight 中不存在 IsMouseOver)或查找跑步的边界几何(无剪辑属性)的方法。
有VisualTreeHelper.FindElementsInHostCoordinates()
下面的代码使用VisualTreeHelper.FindElementsInHostCoordinates来获取点击下的控件。输出列出了 TextBlock,但没有列出 Run,因为 Run 不是 UiElement。
private void theText_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
// get the elements under the click
UIElement uiElementSender = sender as UIElement;
Point clickPos = e.GetPosition(uiElementSender);
var UiElementsUnderClick = VisualTreeHelper.FindElementsInHostCoordinates(clickPos, uiElementSender);
// show the controls
string outputText = "";
foreach (var uiElement in UiElementsUnderClick)
{
outputText += uiElement.GetType().ToString() + "\n";
}
this.outText.Text = outputText;
}
使用带有边距的空文本块将后面的内容隔开到下一行
我还在想这个。您如何计算换行块的正确宽度以将以下内容强制到下一行?太短了,下面的内容仍然会在同一行,在右边。太长,“换行符”将在下一行,后面有内容。调整控件大小时,您必须调整中断的大小。
一些代码是:
TextBlock lineBreak = new TextBlock();
lineBreak.TextWrapping = TextWrapping.Wrap;
lineBreak.Text = " ";
// need adaptive width
lineBreak.Margin = new Thickness(0, 0, 200, 0);