2017-01-24 9 views
0

In einer UWP-App verwende ich einen RichTextBlock, der mit Inhalt gefüllt wird. Es verfügt über eine Zeilenumbruch aktiviert und hat eine maximale Zeilenanzahl festgelegt, so dass es unabhängig von der Länge seines Inhalts nur eine bestimmte Anzahl von Zeilen Rich Text angezeigt wird.Visible Text von RichTextBlock abrufen

Ich würde gerne wissen, ob es eine Möglichkeit gibt herauszufinden, was ist der sichtbare Text?

Also, wenn ich habe:

<RichTextBlock TextWrapping="Wrap" MaxLines="2"> 
    <RichTextBlock.Blocks> 
     <Paragraph> 
      <Paragraph.Inlines> 
       A bunch of runs go in here with text that are several lines 
      </Paragraph.Inlines> 
     </Paragraph> 
    </RichTextBlock.Blocks> 
</RichTextBlock> 

Ich möchte wissen, wie viel von dem Text tatsächlich sichtbar ist.

Ich versuche Fälle zu ermitteln, in denen der Text länger als eine festgelegte Anzahl von Zeilen ist, und am Ende der letzten Zeile ein "... Read More" anzuhängen (die letzten 13 Zeichen durch "... Lesen Sie mehr ")

+0

Sie müssen verwenden „... Lesen Sie weiter“? Wäre ok? – Scavenger

+0

Ja muss es "... Weiterlesen" sein sonst hätte ich gerade TextTrimming = CharacterEllipsis verwendet Leider gibt es keine Möglichkeit, benutzerdefinierten Text anstelle von "..." bei Verwendung von TextTrimming zu verwenden hätte mein Problem gelöst. –

Antwort

1

Also habe ich etwas Code geschrieben, um das Verhalten, das ich will, aber leider ist das eher langsam und ineffizient. Also, wenn Sie es in einer App verwenden, die in erster Linie viel Text anzeigen soll, der abgeschnitten werden muss (wie ein ListView mit vielen Textelementen), würde dies Ihre App perf verlangsamen. Ich würde immer noch gerne wissen, ob es einen besseren Weg gibt, dies zu tun.

Hier ist mein Code (die nur Griffe Run und Hyperlink inlines, so dass Sie andere Arten behandeln ändern müssen werden, die Sie benötigen):

private static void TrimText_Slow(RichTextBlock rtb) 
{ 
    var paragraph = rtb?.Blocks?.FirstOrDefault() as Paragraph; 
    if (paragraph == null) { return; } 

    // Ensure RichTextBlock has passed a measure step so that its HasOverflowContent is updated. 
    rtb.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); 
    if (rtb.HasOverflowContent == false) { return; } 


    // Start from end and remove all inlines that are not visible 
    Inline lastInline = null; 
    var idx = paragraph.Inlines.Count - 1; 
    while (idx >= 0 && rtb.HasOverflowContent) 
    { 
     lastInline = paragraph.Inlines[idx]; 
     paragraph.Inlines.Remove(lastInline); 
     idx--; 
     // Ensure RichTextBlock has passed a measure step now with an inline removed, so that its HasOverflowContent is updated. 
     rtb.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); 
    } 

    // The last inline could be partially visible. The easiest thing to do here is to always 
    // add back the last inline and then remove characters from it until everything is in view. 
    if (lastInline != null) 
    { 
     paragraph.Inlines.Add(lastInline); 
    } 

    // Make room to insert "... Read More" 
    DeleteCharactersFromEnd(paragraph.Inlines, 13); 

    // Insert "... Continue Reading" 
    paragraph.Inlines.Add(new Run { Text = "... " }); 
    paragraph.Inlines.Add(new Run { Text = "Read More", Foreground = new SolidColorBrush(Colors.Blue) }); 

    // Ensure RichTextBlock has passed a measure step now with the new inlines added, so that its HasOverflowContent is updated. 
    rtb.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); 

    // Keep deleting chars until "... Continue Reading" comes into view 
    idx = paragraph.Inlines.Count - 3; // skip the last 2 inlines since they are "..." and "Read More" 
    while (idx >= 0 && rtb.HasOverflowContent) 
    { 
     Run run; 

     if (paragraph.Inlines[idx] is Hyperlink) 
     { 
      run = ((Hyperlink)paragraph.Inlines[idx]).Inlines.FirstOrDefault() as Run; 
     } 
     else 
     { 
      run = paragraph.Inlines[idx] as Run; 
     } 

     if (string.IsNullOrEmpty(run?.Text)) 
     { 
      paragraph.Inlines.Remove(run); 
      idx--; 
     } 
     else 
     { 
      run.Text = run.Text.Substring(0, run.Text.Length - 1); 
     } 

     // Ensure RichTextBlock has passed a measure step now with the new inline content updated, so that its HasOverflowContent is updated. 
     rtb.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); 
    } 
} 

private static void DeleteCharactersFromEnd(InlineCollection inlines, int numCharsToDelete) 
{ 
    if (inlines == null || inlines.Count < 1 || numCharsToDelete < 1) { return; } 

    var idx = inlines.Count - 1; 

    while (numCharsToDelete > 0) 
    { 
     Run run; 

     if (inlines[idx] is Hyperlink) 
     { 
      run = ((Hyperlink)inlines[idx]).Inlines.FirstOrDefault() as Run; 
     } 
     else 
     { 
      run = inlines[idx] as Run; 
     } 

     if (run == null) 
     { 
      inlines.Remove(inlines[idx]); 
      idx--; 
     } 
     else 
     { 
      var textLength = run.Text.Length; 
      if (textLength <= numCharsToDelete) 
      { 
       numCharsToDelete -= textLength; 
       inlines.Remove(inlines[idx]); 
       idx--; 
      } 
      else 
      { 
       run.Text = run.Text.Substring(0, textLength - numCharsToDelete); 
       numCharsToDelete = 0; 
      } 
     } 
    } 
} 
Verwandte Themen