2016-08-02 12 views
2

Gibt es dafür Framework-Unterstützung, oder soll ich einfach meinen eigenen Code dafür schreiben?Wie lange Text in Spalten aufteilen, wie in Zeitungen?

Das Lesen langer Textzeilen ist schwierig und verursacht Ermüdung. Lesbarer Text sollte aus kurzen Zeilen bestehen. Das Problem ist, wenn ich in meiner Anwendung großen horizontalen Platz habe, um mit Text zu bedecken.

In einer guten Anwendung sollte die Präsentationsschicht unabhängig von Datenschicht sein, die in diesem Fall der Text ist. Also brauche ich mehrspaltiges Textlayout, aber das Teilen von Text in Spalten muss vom Programm ausgeführt werden, es kann nicht fest codiert werden.

In HTML/CSS3 ist es einfach. Gibt es Unterstützung in XAML?

Falls nicht, kennen Sie einige Bibliotheken, die mehrspaltige Layouts anzeigen können?

Am besten wäre es, wenn das Steuerelement entscheiden könnte, ob mehrere Spalten verwendet werden sollen. Wenn das Rechteck breiter als größer ist - dann ja. Wenn es größer als breiter ist - dann nein.

+0

Wenn Sie Text sagen, meinen Sie eine Zeichenfolge, die Sie einfach teilen möchten? –

+0

Die Eingabe ist eine Zeichenfolge. Lesen von String-Ressourcen. Aber ich will Spalten als Ergebnis. Genau wie in 'FlowDocument', aber auch in der UWP App. Ich habe eine lange Beschreibung, es ist unlesbar, wenn es bildschirmweit dargestellt wird. Ich bin sehr überrascht, dass 'FlowDocument' in UWP nicht verfügbar ist. Ich habe keine ähnliche Kontrolle gefunden. Es gibt 'RichTextBlock', aber es scheint keine Spaltenunterstützung zu haben. Wie Microsoft angenommen hat, wird UWP nur mit kleinen Bildschirmen verwendet, was nicht sehr "universal" ist. – Harry

Antwort

1

Sie müssen mit DocumentViewer arbeiten, einem WPF-Steuerelement zum Rendern von Dokumenten. Lesen Sie diesen Artikel: https://msdn.microsoft.com/en-us/library/aa970909(v=vs.110).aspx

+1

Bitte fügen Sie einen Beispielcode hinzu, die Antworten sollten eigenständig stehen, ohne dass sie nutzlos werden, wenn eine Verbindung unterbrochen wird – TheLethalCoder

+0

@TheLethalCoder Ich habe gerade ein Beispiel hinzugefügt. Es ist ziemlich einfach, wenn Sie wissen, wo Sie suchen müssen. Ich musste herausfinden, wo das 'Paragraph'-Element passt und welches' UIElemet' die Möglichkeit hat, Spalten zu verwenden und Absätze zu enthalten. Ich dachte, 'FlowDocument' tut es. Und es muss in 'FlowDocumentPageViewer' enthalten sein. Dann musste ich nur die Steuerung verstecken und das ist es. – Harry

1

Vielen Dank an alle, Ihre Antworten mir erlaubt, schnell eine grundlegende WPF Codebeispiel zu erzeugen:

<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> 

Ja, einige manuelle Bearbeitung noch notwendig, aber es ist durchaus gut, wenn ich nur wollen um einige lokalisierte Beschreibungen in einer lesbaren Weise anzuzeigen.

Einige Automatics (wie zum Beispiel, ob die Spalten benötigt werden oder wie breit sie sein sollten) könnten leicht hinzugefügt werden, aber ich werde das Beispiel so einfach wie möglich lassen. Die Steuervorlage muss angewendet werden, um Seitensteuerelemente auszublenden. Wenn der Text größer ist und nicht in eine Seite passt, bleibt nur die ursprüngliche Vorlage.

Dies ist in UWP leider nicht verfügbar. Ist es?

Also müssen wir tiefer gehen. Keine Hilfe von UWP, gut, lass uns eine Kontrolle machen, die zumindest die WPF-Kontrolle machen würde, richtig?

Ohne weitere Umschweife - ReadableBlock Kontrolle:

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; 
       } 
      } 
     } 

    } 

} 

Und einige XAML es zu testen:

<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> 

OK. Kein Scrollen, keine Formatierung, nur Grundlagen. Nur Spalten, feste Menge. Nicht gründlich getestet, so dass es einen oder zwei Fehler geben kann, aber es sollte mit dem Beispieltext gut funktionieren.

Ich denke, es wäre viel schwieriger, wenn wir formatierten Text erlaubten. Oder vielleicht nicht? Nun, dieses Beispiel teilt einfache Zeichenfolgen auf. TextBlock exponiert ContentStart Eigenschaft, die uns Pixelkoordinaten aller Zeichen in TextBlock erhalten können - wenn es nur gemessen wird. Also erstellen wir unsichtbar TextBlock - setzen Sie seine Breite auf die Spaltenbreite und wir suchen, bei welchem ​​Index unser Zeichen außerhalb der verfügbaren Höhe fällt.

Es schlägt mich, wie dieser Hack erweitern formatierten Text zu unterstützen, ich denke, das Problem sehr werden würde „nicht trivial“;)

0

Nun ja, eine Art, wie ich wäre denke eine Schleife erstellen dann hinzufügen Überprüfen Sie dieses Beispiel in einem Textblock, der Inlines verwendet:

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

Sie können VisualStateManager verwenden, um mehrere Spaltenansicht adaptiv zu erstellen. Angenommen, Sie möchten Ihren Text in drei verschiedenen Spalten anzeigen, dann teilen Sie Ihren Text in drei Teile und legen Sie sie als Datenquelle für Ihr Präsentationselement in XAML fest.

<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> 

Wenn das Anwendungsfenster hat eine Breite von weniger als 650 den die Stapelplatte unterhalb einem anderen Set, deshalb haben Sie einzelne Spalten-Ansicht. Wenn die Breite größer als 650 wird, werden sie in drei Spalten unterteilt.

+0

Das ist definitiv ein Teil davon - wir bekommen ein anderes Layout je nach verfügbarem Platz. Aber Sie haben gerade die Textdivision festgeschrieben. Wenn der Text aus Anwendungsressourcen gelesen wird, ist seine Länge unbekannt. Ich denke, es gibt keinen anderen Weg, als Custom ContentControl zu machen, das den verfügbaren Platz misst, dann ein Raster erstellt und den Text in Spalten aufteilt. – Harry

+0

@Harry Sie können das Window.Current.SizeChanged-Ereignis abonnieren und die Breite des aktuellen Fensters bestimmen. Bestimmen Sie entsprechend, wie viele Spalten Sie Ihren Text anzeigen müssen, und teilen Sie dann den Text in die gleiche Anzahl von mehreren Zeichenfolgen auf und weisen Sie diese Zeichenfolgen als Datenquelle Ihren xaml-Elementen zu. In Ihrem xaml make sollte die Anzahl der Spalten die maximale Anzahl der Spalten sein, die Sie unterstützen möchten. Auf diese Weise können Sie erreichen, was Sie wollen. –

+0

Das Bestimmen der Anzahl der Spalten ist hier nicht der schwierige Teil. Der schwierigste Teil besteht darin festzulegen, bei welcher String-Offset-Spalte die Höhe überschritten würde. Ich habe keine Ahnung, wie man das macht, außer dass man dem Spaltenzeichen nach dem Zeichen Text hinzufügt und das 'TextBlock' Element mißt, um' DesiredSize' 'Höhe' zu ​​erhalten. Dies kann jedoch zu langsam sein. – Harry