With the FormattedText class, you can first create formatted text and estimate its size so that you know how much space it takes in the first step. If it is too long, you need to separate separate lines.
Then in the second stage it could be drawn.
Everything can happen on the DrawingContext following way:
protected override void OnRender(System.Windows.Media.DrawingContext dc)
Here is the CustomControl solution:
[ContentProperty("Text")] public class TextBlockLineSplitter : FrameworkElement { public FontWeight FontWeight { get { return (FontWeight)GetValue(FontWeightProperty); } set { SetValue(FontWeightProperty, value); } } public static readonly DependencyProperty FontWeightProperty = DependencyProperty.Register("FontWeight", typeof(FontWeight), typeof(TextBlockLineSplitter), new PropertyMetadata(FontWeight.FromOpenTypeWeight(400))); public double FontSize { get { return (double)GetValue(FontSizeProperty); } set { SetValue(FontSizeProperty, value); } } public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double), typeof(TextBlockLineSplitter), new PropertyMetadata(10.0)); public String FontFamily { get { return (String)GetValue(FontFamilyProperty); } set { SetValue(FontFamilyProperty, value); } } public static readonly DependencyProperty FontFamilyProperty = DependencyProperty.Register("FontFamily", typeof(String), typeof(TextBlockLineSplitter), new PropertyMetadata("Arial")); public String Text { get { return (String)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(String), typeof(TextBlockLineSplitter), new PropertyMetadata(null)); public double Interline { get { return (double)GetValue(InterlineProperty); } set { SetValue(InterlineProperty, value); } } public static readonly DependencyProperty InterlineProperty = DependencyProperty.Register("Interline", typeof(double), typeof(TextBlockLineSplitter), new PropertyMetadata(3.0)); public List<String> Lines { get { return (List<String>)GetValue(LinesProperty); } set { SetValue(LinesProperty, value); } } public static readonly DependencyProperty LinesProperty = DependencyProperty.Register("Lines", typeof(List<String>), typeof(TextBlockLineSplitter), new PropertyMetadata(new List<String>())); protected override void OnRender(DrawingContext drawingContext) { base.OnRender(drawingContext); Lines.Clear(); if (!String.IsNullOrWhiteSpace(Text)) { string remainingText = Text; string textToDisplay = Text; double availableWidth = ActualWidth; Point drawingPoint = new Point();
Using this control (border shown here for effective clipping):
<Border BorderThickness="1" BorderBrush="Red" Height="200" VerticalAlignment="Top"> <local:TextBlockLineSplitter>Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do. Once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, "and what is the use of a book," thought Alice, ...</local:TextBlockLineSplitter> </Border>