Windows8开发实战之-文本布局
我们在展示大量文本的地方就有必须对文进行一个布局了,比如:新闻阅读之类。
先贴个图看看效果:
图中的现实效果就是用到ScrollViewer、StackPanel、RichTextBlock这三个控件来现实。下次看看具体的实现过程和代码。
1、XAML布局
<Grid Margin="20"> <Grid.RowDefinitions> <RowDefinition Height="auto"></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto"></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Button Grid.Row="0" Grid.Column="0" Content="返回" Style="{StaticResource BackButtonStyle}" Click="Button_Click_1" HorizontalAlignment="Left" Margin="44,35,0,0" VerticalAlignment="Top"/> <TextBlock Name="txtTitle" HorizontalAlignment="Center" VerticalAlignment="Bottom" Style="{StaticResource HeaderTextStyle}" Grid.Row="0" Grid.Column="1"></TextBlock> <ScrollViewer Grid.Row="1" Grid.ColumnSpan="2" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden"> <StackPanel Name="stPanel" Orientation="Horizontal"></StackPanel> </ScrollViewer> </Grid>
2、CS代码
1 /// <summary> 2 /// 在此页将要在 Frame 中显示时进行调用。 3 /// </summary> 4 /// <param name="e">描述如何访问此页的事件数据。Parameter 5 /// 属性通常用于配置页。</param> 6 protected override void OnNavigatedTo(NavigationEventArgs e) 7 { 8 if (e.NavigationMode == NavigationMode.New) 9 { 10 FeedItem f = e.Parameter as FeedItem; 11 txtTitle.Text = f.Title; 12 ShowTxt(HtmlUtilities.ConvertToText(f.Content)); 13 14 } 15 } 16 17 private void Button_Click_1(object sender, RoutedEventArgs e) 18 { 19 Frame.GoBack(); 20 } 21 22 const double CT_WIDTH = 400d; //文本块的宽度 23 const double CT_HEIGHT = 600d; //文本块的高度 24 const double CT_MARGIN = 20d; //文本块的边距 25 26 private void ShowTxt(string msg) 27 { 28 stPanel.Children.Clear(); 29 30 // 去掉特殊的换行符 31 msg = msg.Replace(" ", "").Replace("\n", "").Replace("\r", "\n").Replace("\t", ""); 32 msg = Regex.Replace(msg, @"\r\n{1,}", "\r\n"); 33 msg = Regex.Replace(msg, @"\n{1,}", "\n"); 34 msg = Regex.Replace(msg, @"^\n{1,}", ""); 35 36 // 为了支持文本分块,使用RichTextBlock 37 RichTextBlock tbContent = new RichTextBlock(); 38 tbContent.Width = CT_WIDTH; 39 tbContent.Height = CT_HEIGHT; 40 tbContent.TextWrapping = TextWrapping.Wrap; 41 tbContent.Margin = new Thickness(CT_MARGIN); 42 43 44 Paragraph ph = new Paragraph(); 45 ph.TextIndent = 33; 46 47 Run txtRun = new Run(); 48 txtRun.Text = msg; 49 ph.Inlines.Add(txtRun); 50 51 tbContent.Blocks.Add(ph); 52 tbContent.FontSize = 24; 53 54 stPanel.Children.Add(tbContent); 55 // 更新一下状态,方便获取是否有溢出的文本 56 tbContent.UpdateLayout(); 57 bool isflow = tbContent.HasOverflowContent; 58 // 因为除了第一个文本块是RichTextBlock, 59 // 后面的都是RichTextBlockOverflow一个一个接起来的 60 // 所以我们需要两个变量 61 RichTextBlockOverflow oldFlow = null, newFlow = null; 62 if (isflow) 63 { 64 oldFlow = new RichTextBlockOverflow(); 65 oldFlow.Width = CT_WIDTH; 66 oldFlow.Height = CT_HEIGHT; 67 oldFlow.Margin = new Thickness(CT_MARGIN); 68 tbContent.OverflowContentTarget = oldFlow; 69 stPanel.Children.Add(oldFlow); 70 oldFlow.UpdateLayout(); 71 // 继续判断是否还有溢出 72 isflow = oldFlow.HasOverflowContent; 73 } 74 while (isflow) 75 { 76 newFlow = new RichTextBlockOverflow(); 77 newFlow.Height = CT_HEIGHT; 78 newFlow.Width = CT_WIDTH; 79 newFlow.Margin = new Thickness(CT_MARGIN); 80 81 oldFlow.OverflowContentTarget = newFlow; 82 stPanel.Children.Add(newFlow); 83 newFlow.UpdateLayout(); 84 // 继续判断是否还有溢出的文本 85 isflow = newFlow.HasOverflowContent; 86 // 当枪一个变量填充了文本后, 87 // 把第一个变量的引用指向当前RichTextBlockOverflow 88 // 确保OverflowContentTarget属性可以前后相接 89 oldFlow = newFlow; 90 } 91 }