2016-08-02 197 views
2

有沒有對此的任何框架支持,或者我應該爲此編寫自己的代碼?如何在報紙中將長文本分成多列?

閱讀長長的文字很困難,會導致疲勞。可讀文本應由短行組成。問題是在我的應用程序中,我有很大的水平空間來覆蓋文本。

在良好的應用中,表示層應該獨立於數據層,這是本例中的文本。所以我需要多列文本佈局,但是將文本分割成列必須由程序完成,它不能被硬編碼。

在HTML/CSS3中很容易。在XAML中有沒有對它的支持?

如果沒有,你知道一些庫能夠顯示多列布局嗎?

如果控件可以決定是否使用多列,那麼最好的辦法是。如果矩形寬於高 - 那麼是的。如果它比更寬 - 那麼不會。

+0

當你說文字你是指一個字符串,你只是想分開? –

+0

輸入是一個字符串。從字符串資源讀取。但我想要列作爲結果。就像'FlowDocument'一樣,但是在UWP應用中也是如此。我有一個很長的描述,當它在整個屏幕上顯示時是不可讀的。我很驚訝在UWP中'FlowDocument'不可用。我發現沒有類似的控制。有'RichTextBlock',但它似乎沒有列支持。像微軟一樣,UWP只能用於小屏幕,這不是很「普遍」。 – Harry

回答

1

您必須使用DocumentViewer,一個專門用於呈現文檔的WPF控件。閱讀這篇文章:https://msdn.microsoft.com/en-us/library/aa970909(v=vs.110).aspx

+1

請添加一些示例代碼,答案應該站在自己的位置,如果鏈接中斷,則不會顯示無效 – TheLethalCoder

+0

@TheLethalCoder我剛剛添加了一個示例。當你知道在哪裏看,這很容易。我需要找出'Paragraph'元素適合的位置,以及'UIElemet'能夠使用列和包含段落。我想'FlowDocument'確實。它需要包含在'FlowDocumentPageViewer'中。然後,我只需要隱藏控件,就是這樣。 – Harry

1

感謝所有,你的答案讓我迅速地產生一個基本的WPF代碼示例:

<Window x:Class="TextFlow.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:TextFlow" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525" Background="Black" Foreground="Gray"> 
    <Window.Resources> 
     <ControlTemplate x:Key="NoPageControls" TargetType="{x:Type FlowDocumentPageViewer}"> 
      <AdornerDecorator> 
       <DocumentPageView FlowDocumentPageViewer.IsMasterPage="True" /> 
      </AdornerDecorator> 
     </ControlTemplate> 
    </Window.Resources> 
    <Grid> 
     <FlowDocumentPageViewer Template="{StaticResource NoPageControls}"> 
      <FlowDocument ColumnWidth="200" FontFamily="Segoe UI" FontSize="10"> 
       <Paragraph> 
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vitae purus pellentesque, ultricies magna a, egestas nisl. Quisque eu risus quis elit posuere imperdiet. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla sagittis, felis at luctus tempus, metus dolor ultricies mi, vitae aliquet justo libero non arcu. Suspendisse potenti. Maecenas luctus rutrum lorem non congue. Sed vitae blandit felis. Nullam eu leo non dui vulputate tincidunt id eu odio. Etiam risus velit, consequat vel tortor in, condimentum vestibulum est. Sed maximus elementum erat nec fermentum. 
       </Paragraph> 
       <Paragraph> 
        Donec nec ex dignissim, ornare arcu eu, fermentum ipsum. Cras ullamcorper blandit quam, in pulvinar justo sodales quis. Vivamus sed tincidunt augue, nec convallis lorem. Phasellus lobortis nibh sem, sit amet suscipit tellus dapibus at. Aliquam arcu tellus, aliquet at cursus sodales, ornare a sem. Morbi sollicitudin orci et hendrerit ullamcorper. In non faucibus risus. Morbi eget metus pharetra quam consequat pretium quis ac enim. Integer scelerisque elit malesuada pharetra condimentum. Aliquam erat volutpat. Ut at consectetur erat. Phasellus pulvinar consequat erat quis placerat. Cras tortor mi, tempor ultricies sodales at, faucibus quis lacus. Morbi semper vestibulum odio eget tempor. Praesent at mollis erat. Praesent sollicitudin nulla sit amet magna fermentum porta. 
       </Paragraph> 
       <Paragraph> 
        Proin tincidunt ex interdum, sodales leo non, fringilla tellus. Vestibulum eget posuere purus, et aliquam arcu. Sed ac dolor ullamcorper, rutrum sapien sit amet, convallis enim. Mauris a faucibus augue. Morbi porta nunc ac ligula suscipit consequat. Curabitur in interdum elit. Pellentesque tempor tempor tellus, ut bibendum elit consequat vitae. Fusce commodo ac nunc ut pretium. Vestibulum ut vulputate est. Nullam pharetra ornare elementum. Nullam eros nunc, tincidunt at porta sit amet, rutrum in mauris. Vivamus id ante sit amet velit pulvinar interdum. Cras efficitur egestas nunc id tempor. Vivamus eu enim vitae lorem molestie tincidunt nec et ex. Integer nec turpis nisi. 
       </Paragraph> 
      </FlowDocument> 
     </FlowDocumentPageViewer> 
    </Grid> 
</Window> 

是,一些手工加工仍是必要的,但它是非常好的,當我只是想以可讀的方式顯示一些本地化的描述。

可以很容易地添加一些自動裝置(如確定是否需要列或它們應該有多寬),但我會盡可能地簡化示例。必須應用控件模板才能隱藏頁面控件。如果文字較大並且不適合放在一個頁面中 - 您只需保留原始模板。

很抱歉無法在UWP中使用。是嗎?

所以,我們需要更深入。沒有UWP的幫助,沒問題,讓我們做一個控制,至少可以做什麼WPF控制,對吧?

事不宜遲 - ReadableBlock控制:

using System.Collections.Generic; 
using Windows.Foundation; 
using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 
using Windows.UI.Xaml.Documents; 

namespace ReadableBlockDemo.Controls { 
    public sealed class ReadableBlock : ContentControl { 

     public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(ReadableBlock), null); 

     public static readonly DependencyProperty TextAlignmentProperty = 
      DependencyProperty.Register("TextAlignment", typeof(TextAlignment), typeof(ReadableBlock), new PropertyMetadata(TextAlignment.Left)); 

     public static readonly DependencyProperty ColumnsProperty = 
      DependencyProperty.Register("Columns", typeof(int), typeof(ReadableBlock), new PropertyMetadata(1)); 

     public static readonly DependencyProperty ColumnSpacingProperty = 
      DependencyProperty.Register("ColumnSpacing", typeof(double), typeof(ReadableBlock), new PropertyMetadata(10d)); 

     public string Text { 
      get { return (string)GetValue(TextProperty); } 
      set { SetValue(TextProperty, value); } 
     } 

     public TextAlignment TextAlignment { 
      get { return (TextAlignment)GetValue(TextAlignmentProperty); } 
      set { SetValue(TextAlignmentProperty, value); } 
     } 

     public int Columns { 
      get { return (int)GetValue(ColumnsProperty); } 
      set { SetValue(ColumnsProperty, (int)value); } 
     } 

     public double ColumnSpacing { 
      get { return (double)GetValue(ColumnSpacingProperty); } 
      set { SetValue(ColumnSpacingProperty, (double)value); } 
     } 

     public new string Content { 
      get { return (string)GetValue(ContentProperty); } 
      set { base.Content = null; SetValue(ContentProperty, Text = (string)value); RenderText(); } 
     } 

     private StackPanel Container => base.Content as StackPanel; 

     private double AvailableWidth; 

     private double AvailableHeight; 

     private TextBlock[] Blocks; 

     private double ColumnWidth; 

     private bool IsTextRenderingAvailable; 

     public ReadableBlock() { 
      Loaded += ReadableBlock_Loaded; 
     } 

     private void ReadableBlock_Loaded(object sender, RoutedEventArgs e) { 
      LayoutUpdated += ReadableBlock_LayoutUpdated; 
      InvalidateArrange(); 
     } 

     private void ReadableBlock_LayoutUpdated(object sender, object e) { 
      if (ActualWidth != AvailableWidth || ActualHeight != AvailableHeight) OnAvailableSizeChanged(); 
     } 

     private void OnAvailableSizeChanged() { 
      IsTextRenderingAvailable = true; 
      AvailableWidth = ActualWidth; 
      AvailableHeight = ActualHeight; 
      double n = Columns; 
      double s = ColumnSpacing; 
      ColumnWidth = (AvailableWidth - ((n - 1d) * s))/n; 
      if (Blocks == null) CreateColumns(); 
      RenderText(); 
     } 

     private void CreateColumns() { 
      var container = new StackPanel { Orientation = Orientation.Horizontal }; 
      var columns = Columns; 
      var spacing = ColumnSpacing; 
      var blocks = new List<TextBlock>(); 
      TextBlock block; 
      for (int i = 0; i < columns; i++) { 
       blocks.Add(block = new TextBlock { TextWrapping = TextWrapping.Wrap, TextAlignment = TextAlignment, Width = ColumnWidth, Height = AvailableHeight }); 
       if (i > 0) block.Margin = new Thickness(spacing, 0, 0, 0); 
       container.Children.Add(block); 
      } 
      base.Content = container; 
      Blocks = blocks.ToArray(); 
     } 

     private int GetSplitOffset(string text) { 
      var m = new TextBlock { FontFamily = FontFamily, FontSize = FontSize, TextWrapping = TextWrapping.Wrap, TextAlignment = TextAlignment }; 
      m.Text = text; 
      m.Measure(new Size(ColumnWidth, double.PositiveInfinity)); 
      if (m.DesiredSize.Height < AvailableHeight) return -1; 
      var p = m.ContentStart; 
      var r = p.GetCharacterRect(LogicalDirection.Forward); 
      for (int i = 0, l = text.Length; i < l && r.Bottom < AvailableHeight; i++) { 
       p = p.GetPositionAtOffset(1, LogicalDirection.Forward); 
       r = p.GetCharacterRect(LogicalDirection.Forward); 
      } 
      return p.Offset - 2; 
     } 

     private bool SetBlock(int i, string text) { 
      if (i >= Blocks.Length) return false; 
      var block = Blocks[i]; 
      block.Width = ColumnWidth; 
      block.Height = AvailableHeight; 
      block.Text = text; 
      return true; 
     } 

     private void RenderText() { 
      if (!IsTextRenderingAvailable || Text == null) return; 
      int i = 0, splitOffset = 0, n = Blocks.Length; 
      string text = Text; 
      for (i = 0; i < n; i++) Blocks[i].Text = ""; 
      for (i = 0; i < n; i++) { 
       splitOffset = GetSplitOffset(text); 
       if (splitOffset > 0) { 
        if (!SetBlock(i, text.Substring(0, splitOffset))) return; 
        if (!SetBlock(i + 1, text = text.Substring(splitOffset))) return; 
       } 
       else { 
        SetBlock(i, text); 
        return; 
       } 
      } 
     } 

    } 

} 

一些XAML,並對其進行測試:

<Page 
    x:Class="ReadableBlockDemo.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:ReadableBlockDemo" 
    xmlns:Controls="using:ReadableBlockDemo.Controls" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" 
    Background="#444" 
    Foreground="Gray" 
    > 
    <Grid> 
     <Controls:ReadableBlock Columns="4" ColumnSpacing="25" TextAlignment="Justify" Margin="25"> 
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tempor ipsum massa, ac lacinia libero sagittis lobortis. Donec pretium ex quis massa eleifend dignissim. Maecenas quis est odio. Proin facilisis mollis purus, vitae dapibus lacus interdum ac. Sed molestie id lorem vel volutpat. Ut vitae quam sem. Pellentesque convallis elementum ipsum commodo porttitor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; 
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sed porta eros. Pellentesque eget dolor euismod, fermentum orci vitae, ullamcorper mauris. Aliquam tempus hendrerit sollicitudin. Nunc sed erat quis ligula dictum convallis. Mauris eget finibus odio. Aenean sagittis congue purus, at elementum mi rhoncus ut. Suspendisse hendrerit dictum eleifend. Nullam scelerisque, eros ac euismod semper, velit sapien tincidunt purus, a tempus enim ante ut turpis. In vehicula arcu vitae nunc eleifend, id porta felis consequat. 
      Praesent vel tincidunt dui. Ut ut turpis lacus. Nullam accumsan laoreet elit eu suscipit. Cras aliquet pellentesque fringilla. Nullam ut consectetur nisi, non tristique quam. Suspendisse vitae gravida ipsum. Fusce ac enim non arcu rutrum sollicitudin. Aliquam in odio id tellus venenatis egestas et quis sapien. Etiam scelerisque ultrices tellus, quis dignissim leo gravida id. 
      Etiam ut elit tortor. Fusce fringilla accumsan urna eu viverra. Nunc porttitor lorem vitae magna ultrices lacinia. Etiam posuere sed dui nec gravida. Aenean fermentum turpis vehicula, blandit arcu id, mollis nulla. Praesent laoreet tellus vitae lectus consequat interdum. Duis interdum feugiat interdum. 
      Nam ut maximus est. Vestibulum sagittis eros ut diam ultrices eleifend. Praesent purus quam, luctus quis arcu at, interdum dapibus leo. Vivamus eget massa in leo malesuada egestas quis eget ipsum. Etiam consequat ullamcorper est, in ultricies lacus lobortis commodo. Nullam feugiat libero vitae convallis pellentesque. Pellentesque vitae tristique massa. In sollicitudin pretium nisl sit amet dignissim. Curabitur sodales fringilla ex, sit amet gravida lacus dignissim tempus. Aenean libero lectus, viverra eu eros in, pellentesque accumsan elit. Proin porttitor metus nulla, sit amet vulputate mauris finibus ut. Phasellus viverra risus sapien, eget sodales neque rhoncus vel. Nam quis ullamcorper nulla. 
      Duis sed ante dignissim, consequat orci in, iaculis nisi. Etiam nec interdum magna. Donec pharetra fermentum mi, eu aliquet diam hendrerit eget. Aenean vitae ligula sem. Sed at dignissim lorem. Proin vulputate massa eleifend, sagittis leo sit amet, condimentum mi. Curabitur nec vulputate nibh. Nunc ut dictum sapien. Praesent eu rhoncus lectus. Nullam eu auctor dui. Sed accumsan leo et ligula tempus semper. Suspendisse sed magna ut lectus pharetra malesuada. 
      Nullam pretium ligula non elit tempus imperdiet. In convallis a mauris vitae venenatis. Morbi pulvinar placerat ante nec tristique. Sed sodales leo in erat fermentum malesuada. Nullam vel turpis ut nulla tempus faucibus. Fusce dictum odio vel felis fringilla, a iaculis urna ultricies. Sed at mauris dolor. Aenean et vulputate libero, at sollicitudin leo. Morbi pretium gravida turpis ac bibendum. Aliquam lacinia mauris ut ante pharetra accumsan. Ut hendrerit, diam in iaculis egestas, justo magna pulvinar sapien, ut pellentesque purus orci id magna. Morbi egestas vestibulum dui, a ullamcorper turpis. Aenean molestie luctus lacus, vel pellentesque elit tincidunt sit amet. Suspendisse eu cursus enim. In eu libero a ipsum interdum aliquam quis blandit quam. 
      Fusce tortor nisi, pretium non dolor vitae, pretium condimentum ex. Cras facilisis odio tortor, et scelerisque quam volutpat non. Nam fermentum, velit in molestie venenatis, odio ante dapibus nulla, sed luctus ex urna sit amet lectus. Donec sit amet eros at nulla tempor venenatis. Cras nec purus porttitor dolor pretium auctor. Mauris sed ligula eget libero egestas tempus quis eu ipsum. Duis fermentum egestas libero. Praesent a mi ut felis facilisis pharetra id vel nulla. 
      Aenean dolor leo, placerat ac lobortis ut, tincidunt sit amet ex. Pellentesque at convallis massa. Vivamus fermentum eu augue vel sollicitudin. Donec dictum libero sem, et bibendum ex ultricies eget. Sed eu feugiat odio. Sed eget ex congue, dapibus magna ac, finibus diam. Nunc sollicitudin euismod dictum. Nullam rutrum mauris ut ipsum finibus, et euismod arcu sodales. In pellentesque molestie nunc, eget pellentesque metus varius et. Morbi augue nisl, aliquet eu scelerisque at, dictum eu elit. Quisque id ex quis urna facilisis rutrum nec in risus. Sed lorem justo, tempus at ante quis, cursus ultrices tellus. Donec lacinia varius lacus, vitae molestie velit auctor vitae. Aenean vulputate ullamcorper justo sit amet consectetur. Fusce vel risus mattis augue ultrices molestie. Donec sed rhoncus diam. 
      Nulla condimentum cursus massa semper suscipit. Cras non porta diam. Donec sed erat eu lectus vehicula hendrerit. Proin a ex tellus. Morbi aliquet dolor in ante lobortis, consequat aliquam dolor cursus. Sed molestie odio massa, a consectetur turpis pellentesque eget. Maecenas quis pharetra ligula, non rutrum libero. Aenean maximus nibh vel nisl elementum imperdiet. Integer et urna eu velit porttitor eleifend. Nunc et pharetra nisl. Nulla porttitor pellentesque mi. Suspendisse porta a ipsum at interdum. 
     </Controls:ReadableBlock> 
    </Grid> 
</Page> 

確定。沒有滾動,沒有格式,只是基礎知識。只是列,固定金額。 未經徹底測試,因此可能存在一兩個錯誤,但它應該可以在示例文本中正常工作。

我認爲如果我們允許格式化文本將會更困難。或者可能不是?那麼,這個例子拆分了純字符串。 TextBlock曝光ContentStart屬性,它允許我們獲取TextBlock中所有字符的像素座標 - 如果它僅被測量。因此,我們創建了無形的TextBlock - 將其寬度設置爲列寬度,我們搜索角色落在可用高度以外的索引。

這可叫我如何延長這個黑客以支持格式的文本,我認爲這個問題將變得非常「不平凡」;)

0

好一個方法,我想將創建一個循環然後將其添加使用內聯一個文本塊,檢查這個例子:

string teststring = "fdssssssfdsfdsfjhjkdhfjkdsjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkfsdfdsfdscccxcxvdsfsfdsfsdf"; 

    private void button2_Click(object sender, RoutedEventArgs e) 
    { 
     for (int i = 0; i < teststring.Length; i += 10) 
     { 
      if ((i + 10) < teststring.Length) 
      { 
       textBlock.Inlines.Add(new Run { Text = Environment.NewLine + teststring.Substring(i, 10) }); 
      } 
      else 
      { 
       textBlock.Inlines.Add(new Run { Text = Environment.NewLine + teststring.Substring(i) }); 
      } 
     } 
    } 
1

您可以使用VisualStateManager自適應地創建多個列視圖。假設您想要將文本顯示爲三個不同的列,然後將文本分爲三部分,並將它們設置爲XAML中的演示文稿元素的數據源。

<Page 
x:Class="App7.MainPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="using:AdaptiveLayoutExample" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d"> 

<Grid Name="LayoutRoot" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <VisualStateManager.VisualStateGroups> 
     <VisualStateGroup x:Name="VisualStateGroup"> 
      <VisualState x:Name="Wide"> 
       <VisualState.StateTriggers> 
        <AdaptiveTrigger MinWindowWidth="650" /> 
       </VisualState.StateTriggers> 
       <VisualState.Setters> 
        <Setter Target="First.(Grid.Row)" Value="0" /> 
        <Setter Target="First.(Grid.Column)" Value="0" /> 
        <Setter Target="Second.(Grid.Row)" Value="0" /> 
        <Setter Target="Second.(Grid.Column)" Value="1" /> 
        <Setter Target="Third.(Grid.Row)" Value="0" /> 
        <Setter Target="Third.(Grid.Column)" Value="2" /> 

        <Setter Target="First.(Grid.ColumnSpan)" Value="1" /> 
        <Setter Target="Second.(Grid.ColumnSpan)" Value="1" /> 
        <Setter Target="Third.(Grid.ColumnSpan)" Value="1" /> 
       </VisualState.Setters> 
      </VisualState> 
      <VisualState x:Name="Narrow"> 
       <VisualState.StateTriggers> 
        <AdaptiveTrigger MinWindowWidth="0" /> 
       </VisualState.StateTriggers> 
       <VisualState.Setters> 
        <Setter Target="First.(Grid.Row)" Value="0" /> 
        <Setter Target="First.(Grid.Column)" Value="0" /> 
        <Setter Target="Second.(Grid.Row)" Value="1" /> 
        <Setter Target="Second.(Grid.Column)" Value="0" /> 
        <Setter Target="Third.(Grid.Row)" Value="2" /> 
        <Setter Target="Third.(Grid.Column)" Value="0" /> 

        <Setter Target="First.(Grid.ColumnSpan)" Value="3" /> 
        <Setter Target="Second.(Grid.ColumnSpan)" Value="3" /> 
        <Setter Target="Third.(Grid.ColumnSpan)" Value="3" /> 
       </VisualState.Setters> 
      </VisualState> 
     </VisualStateGroup> 
    </VisualStateManager.VisualStateGroups> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="*"/> 
    </Grid.RowDefinitions> 
    <ScrollViewer Grid.Row="1"> 
     <Grid> 
      <Grid.RowDefinitions> 
       <RowDefinition /> 
       <RowDefinition /> 
       <RowDefinition /> 
      </Grid.RowDefinitions> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*"/> 
       <ColumnDefinition Width="*"/> 
       <ColumnDefinition Width="*"/> 
      </Grid.ColumnDefinitions> 

      <StackPanel Name="First" Margin="20,20,0,0"> 
       <TextBlock TextWrapping="Wrap"> 
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
        Cras id orci iaculis, aliquet nibh at, dictum lorem. Vivamus 
        tempus tristique sollicitudin. Etiam interdum et lectus 
        semper molestie. Phasellus lobortis felis quis risus posuere, 
        id molestie mi sagittis. Cras odio leo, dictum vitae euismod et, 
        lacinia non lectus. Integer quis massa velit. Ut at dui 
        rutrum, venenatis dui a, pretium arcu. Nunc eu urna pulvinar, 
        condimentum sapien non, consectetur turpis. Pellentesque dapibus, 
        eros ac rutrum congue, quam dolor rhoncus nunc, ut sagittis nisl 
        urna in ante. Sed nunc libero, aliquet at elit eget, vulputate 
        ultrices leo. Aliquam vel sapien varius, blandit dui ac, 
        fringilla metus. Lorem ipsum dolor sit amet, consectetur 
        adipiscing elit. Fusce vehicula odio sit amet tortor lobortis 
        sagittis. Nullam vestibulum tortor eget risus vulputate, at 
        semper nunc pharetra. Nullam fringilla dapibus turpis non 
        vehicula. Proin sollicitudin sapien enim, at interdum risus 
        cursus quis. 
       </TextBlock> 
      </StackPanel> 
      <StackPanel Name="Second" Grid.Row="1" Margin="20,20,0,0"> 
       <TextBlock TextWrapping="Wrap"> 
        Nam sollicitudin justo quis consequat molestie. Etiam dictum 
        sodales tellus, ut consectetur magna sodales in. Phasellus viverra 
        volutpat porttitor. Pellentesque sed condimentum neque. In 
        ultrices ex ac lacus tincidunt, eget euismod urna cursus. Donec tempor 
        mauris leo, ac cursus nisl tempus a. Aliquam dignissim eleifend lorem a 
        facilisis. Praesent tincidunt semper ante non ornare. Cras eleifend 
        eros et tincidunt auctor. Duis lorem nunc, dictum dignissim est vitae, 
        luctus dapibus lacus. Donec fringilla ipsum nec diam sagittis, 
        nec suscipit metus maximus. Aliquam aliquam non ante tincidunt 
        fringilla. Phasellus auctor, nisl non rutrum imperdiet, arcu 
        purus pretium libero, nec eleifend metus turpis vel ante. Phasellus 
        sit amet rhoncus lectus. 
       </TextBlock> 
      </StackPanel> 
      <StackPanel Name="Third" Grid.Row="2" Margin="20,20,0,0"> 
       <TextBlock TextWrapping="Wrap"> 
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
        Cras id orci iaculis, aliquet nibh at, dictum lorem. Vivamus 
        tempus tristique sollicitudin. Etiam interdum et lectus 
        semper molestie. Phasellus lobortis felis quis risus posuere, 
        id molestie mi sagittis. Cras odio leo, dictum vitae euismod et, 
        lacinia non lectus. Integer quis massa velit. Ut at dui 
        rutrum, venenatis dui a, pretium arcu. Nunc eu urna pulvinar, 
        condimentum sapien non, consectetur turpis. Pellentesque dapibus, 
        eros ac rutrum congue, quam dolor rhoncus nunc, ut sagittis nisl 
        urna in ante. Sed nunc libero, aliquet at elit eget, vulputate 
        ultrices leo. Aliquam vel sapien varius, blandit dui ac, 
        fringilla metus. Lorem ipsum dolor sit amet, consectetur 
        adipiscing elit. Fusce vehicula odio sit amet tortor lobortis 
        sagittis. Nullam vestibulum tortor eget risus vulputate, at 
        semper nunc pharetra. Nullam fringilla dapibus turpis non 
        vehicula. Proin sollicitudin sapien enim, at interdum risus 
        cursus quis. 
       </TextBlock> 
      </StackPanel> 
     </Grid> 
    </ScrollViewer> 
</Grid> 

當應用程序窗口具有寬度小於650它設置低於另一個的堆疊面板,因此,你有單個列圖。當寬度大於650時,它將它們分成三列。

+0

這絕對是它的一部分 - 我們根據可用空間得到不同的佈局。但是你只是對文本劃分進行了硬編碼。如果從應用程序資源中讀取文本,則其長度未知。我認爲除了製作自定義ContentControl來衡量可用空間,然後創建網格並將文本拆分爲列之外別無他法。 – Harry

+0

@Harry您可以訂閱Window.Current.SizeChanged事件並確定當前窗口的寬度。據此確定需要顯示文本的列數,然後將文本拆分爲相同數量的多個字符串,並將這些字符串作爲數據源分配給xaml元素。在你的xaml中,列數應該是你想要支持的最大列數。通過這種方式,你可以實現你想要的。 –

+0

確定列數並不困難。困難的部分是確定哪個字符串偏移列高度將被超過。我不知道如何去做,除了在字符後面添加文本到列字符並測量'TextBlock'元素來獲取'DesiredSize'.'Height'。儘管這可能太慢了。 – Harry