老周的部落格http://blog.csdn.net/tcjiaan,轉載請註明原作者和出處。
準確地說,本文是與各位分享一下小技巧。也不知道各位喜不喜歡。
嗯,廢話就不說了,先看看我要實現什麼樣的運行結果。
是的,很像報紙的排版效果,那麼,怎麼做到的呢?
這就要提到一個類——RichTextBlockOverflow。他的用途就是,當RichTextBlock中的文本溢出後(就是當前RichTextBlock顯示不完比較長的文本),可以在RichTextBlockOverflow上接著顯示。
RichTextBlock的OverflowContentTarget屬性設定為要接著顯示文本的RichTextBlockOverflow,如果第一個RichTextBlockOverflow仍然不夠用,則可以添加更多的RichTextBlockOverflow,只要把前一個的RichTextBlockOverflow的OverflowContentTarget屬性設定為新的RichTextBlockOverflow,以此類推。
要判斷文本是否溢出,可以通過HasOverflowContent屬性獲得。
好了,大概原理說了,下面就是動手實現了。
1、啟動Visual Studio for Win 8 ,建立一個項目。
2、MainPage.xaml比較簡單,按鈕是為了選取一個較長的文字檔,文字框用於輸入字型大小。用於排列文本的是一個StackPanel。
<Page x:Class="App1.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App1" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="25"> <Button Content="開啟檔案" Click="onClick"/> <TextBlock Text="字型大小" Margin="37,0,0,0" FontSize="24" VerticalAlignment="Center"/> <TextBox Name="txtSize" VerticalAlignment="Center" Margin="8,0,0,0" Width="130" Text="16"> <TextBox.InputScope> <InputScope> <InputScope.Names> <InputScopeName NameValue="Number"/> </InputScope.Names> </InputScope> </TextBox.InputScope> </TextBox> </StackPanel> <ScrollViewer Margin="15" Grid.Row="1" HorizontalScrollBarVisibility="Auto" HorizontalScrollMode="Auto"> <StackPanel Name="stPanel" Orientation="Horizontal" /> </ScrollViewer> </Grid></Page>
3、對於背景代碼,先貼出完整的吧。
using System;using System.Collections.Generic;using System.IO;using System.Linq;using Windows.Foundation;using Windows.Foundation.Collections;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls;using Windows.UI.Xaml.Controls.Primitives;using Windows.UI.Xaml.Data;using Windows.UI.Xaml.Input;using Windows.UI.Xaml.Media;using Windows.UI.Xaml.Navigation;using Windows.Storage;using Windows.Storage.Streams;using Windows.Storage.Pickers;using Windows.UI.Xaml.Documents;namespace App1{ public sealed partial class MainPage : Page { const double CT_WIDTH = 400d; //文字區塊的寬度 const double CT_HEIGHT = 500d; //文字區塊的高度 const double CT_MARGIN = 25d; //文字區塊的邊距 public MainPage() { this.InitializeComponent(); } private async void onClick(object sender, RoutedEventArgs e) { // 從文字檔中讀取內容 FileOpenPicker opPicker = new FileOpenPicker(); opPicker.FileTypeFilter.Add(".txt"); opPicker.CommitButtonText = "開啟"; opPicker.SuggestedStartLocation = PickerLocationId.Desktop; StorageFile file = await opPicker.PickSingleFileAsync(); if (file != null) { using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read)) { // 從流中讀取文本,考慮utf-8讀出來的是亂碼, // 改用Stream類來讀取 // 使用gb2312編碼格式 string msg = string.Empty; using (Stream strm = stream.AsStream()) { StreamReader render = new StreamReader(strm, System.Text.Encoding.GetEncoding("gb2312")); msg = render.ReadToEnd(); } // 去掉特殊的分行符號 msg = msg.Replace(" ", "").Replace("\n", "").Replace("\r","\n").Replace("\t",""); stPanel.Children.Clear(); // 為了支援文本分塊,使用RichTextBlock RichTextBlock tbContent = new RichTextBlock(); tbContent.Width = CT_WIDTH; tbContent.Height = CT_HEIGHT; tbContent.TextWrapping = TextWrapping.Wrap; tbContent.Margin = new Thickness(CT_MARGIN); Paragraph ph = new Paragraph(); ph.TextIndent = 33; Run txtRun = new Run(); txtRun.Text = msg; ph.Inlines.Add(txtRun); tbContent.Blocks.Add(ph); tbContent.FontSize = Convert.ToDouble(txtSize.Text); stPanel.Children.Add(tbContent); // 更新一下狀態,方便擷取是否有溢出的文本 tbContent.UpdateLayout(); bool isflow = tbContent.HasOverflowContent; // 因為除了第一個文字區塊是RichTextBlock, // 後面的都是RichTextBlockOverflow一個一個接起來的 // 所以我們需要兩個變數 RichTextBlockOverflow oldFlow = null, newFlow = null; if (isflow) { oldFlow = new RichTextBlockOverflow(); oldFlow.Width = CT_WIDTH; oldFlow.Height = CT_HEIGHT; oldFlow.Margin = new Thickness(CT_MARGIN); tbContent.OverflowContentTarget = oldFlow; stPanel.Children.Add(oldFlow); oldFlow.UpdateLayout(); // 繼續判斷是否還有溢出 isflow = oldFlow.HasOverflowContent; } while (isflow) { newFlow = new RichTextBlockOverflow(); newFlow.Height = CT_HEIGHT; newFlow.Width = CT_WIDTH; newFlow.Margin = new Thickness(CT_MARGIN); oldFlow.OverflowContentTarget = newFlow; stPanel.Children.Add(newFlow); newFlow.UpdateLayout(); // 繼續判斷是否還有溢出的文本 isflow = newFlow.HasOverflowContent; // 當槍一個變數填充了文本後, // 把第一個變數的引用指向當前RichTextBlockOverflow // 確保OverflowContentTarget屬性可以前後相接 oldFlow = newFlow; } } } } }}
其實,重點就是迴圈加入文字區塊的地方,代碼中我也做了注釋。