Pollitzer
Pollitzer

Reputation: 1620

How to inject a formatted paragraph into a TextBlock?

I'm trying to transmit the formatted content of a paragraph to a TextBlock, but the formatting disappears:

// Create a formatted paragraph
Paragraph para = new Paragraph();
para.FontSize = 25;
para.FontWeight = FontWeights.Bold;
para.Inlines.Add(new Run("Text of paragraph."));

// Create a span with the content of the paragraph (FontSize 25 and FontWeight Bold stay alive)
Span span = new Span(para.ContentStart, para.ContentEnd);

// Create a TextBlock with the span (FontSize 25 and FontWeight Bold get lost)
TextBlock textBlock = new TextBlock();
textBlock.Inlines.Add(span);

What could be done to keep the formatting? Thanks in advance.

Update
The formatting of the paragraph is known at runtime, so I can't apply property values one by one manually.

Update 2
The background of the question is that I want to measure the length of formatted paragraphs if they are stretched to one line. This can be done by a TextBlock. The paragraphs are located in TableCells, I want to adjust the column widths automatically.

Upvotes: 0

Views: 6234

Answers (4)

Pollitzer
Pollitzer

Reputation: 1620

I reached the following solution:

// Create a formatted Paragraph
Paragraph para = new Paragraph();
para.FontSize = 25;
para.FontWeight = FontWeights.Bold;
para.Inlines.Add(new Run("Text of paragraph."));

// Clone all Inlines
List<Inline> clonedInlines = new List<Inline>();
foreach (Inline inline in para.Inlines)
{
    Inline clonedInline = ElementClone<Inline>(inline);
    clonedInlines.Add(clonedInline);
}

// Get all Paragraph properties with a set value
List<DependencyProperty> depProps = DepPropsGet(para, PropertyFilterOptions.SetValues);

// Apply the Paragraph values to each Inline
foreach (DependencyProperty depProp in depProps)
{
    object propValue = para.GetValue(depProp);

    foreach (Inline clonedInline in clonedInlines)
    {
        // Can the Inline have the value?
        if (depProp.OwnerType.IsAssignableFrom(typeof(Inline)))
        {
            // Apply the Paragraph value
            clonedInline.SetValue(depProp, propValue);
        }
    }
}

// Create a TextBlock with the same properties as the Paragraph
TextBlock textBlock = new TextBlock();
textBlock.Inlines.AddRange(clonedInlines);

/// <summary>
/// Cloner.
/// </summary>
public static T ElementClone<T>(T element)
{
    // Element to Stream
    MemoryStream memStream = new MemoryStream();
    XamlWriter.Save(element, memStream);

    // Cloned element from Stream
    object clonedElement = null;
    if (memStream.CanRead)
    {
        memStream.Seek(0, SeekOrigin.Begin);
        clonedElement = XamlReader.Load(memStream);
        memStream.Close();
    }
    return (T)clonedElement;
}

/// <summary>
/// Property-Getter.
/// </summary>
public static List<DependencyProperty> DepPropsGet(DependencyObject depObj, PropertyFilterOptions filter)
{
    List<DependencyProperty> result = new List<DependencyProperty>();

    foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(depObj, new Attribute[] { new PropertyFilterAttribute(filter) }))
    {
        DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(pd);

        if (dpd != null)
        {
            result.Add(dpd.DependencyProperty);
        }
    }

    return result;
}

Upvotes: 0

nepdev
nepdev

Reputation: 977

Contrary to what @un-lucky says, TextBlock does have this formatting capability.

Check out this article.

By applying the styles directly to the span, you'll get it persisted in the text box.

Excerpt:

                     TextBlock tb = new TextBlock();
                    tb.TextWrapping = TextWrapping.Wrap;
                    tb.Margin = new Thickness(10);
                    tb.Inlines.Add("An example on ");
                    tb.Inlines.Add(new Run("the TextBlock control ") { FontWeight = FontWeights.Bold });
                    tb.Inlines.Add("using ");
                    tb.Inlines.Add(new Run("inline ") { FontStyle = FontStyles.Italic });
                    tb.Inlines.Add(new Run("text formatting ") { Foreground = Brushes.Blue });
                    tb.Inlines.Add("from ");
                    tb.Inlines.Add(new Run("Code-Behind") { TextDecorations = TextDecorations.Underline });
                    tb.Inlines.Add(".");

Update Got your update, but you can take the fonts and styles from the paragraph, and then apply them directly. At least it seems so from your sample above.

TextBlock tb = new TextBlock();

Paragraph para = new Paragraph();
para.FontSize = 25;
para.FontWeight = FontWeights.Bold;
para.Inlines.Add(new Run("new paragraph"));

Span span = new Span(para.ContentStart, para.ContentEnd);
span.FontWeight = para.FontWeight;
span.FontSize = para.FontSize;

tb.Inlines.Add(span);

Does this work for you?

Upvotes: 1

Rohit
Rohit

Reputation: 10246

Instead of TextBlock you can use RichTextBox and achieve the necessary formatting Here is a sample code

// Create a formatted paragraph
        Paragraph para = new Paragraph();
        para.FontSize = 25;
        para.FontWeight = FontWeights.Bold;
        para.Inlines.Add(new Run("Text of paragraph."));

        Myrichtextboxtbx.Document.Blocks.Add(para);

and then add your richtextbox to xaml

Upvotes: 0

sujith karivelil
sujith karivelil

Reputation: 29036

Formatting cannot be applied to the TextBlock, it is similar to a Label, if you need formating then you can use <RichTextBox/> instead. you can make it ReadOnly to avoid editing.

Example:

   <RichTextBox Margin="10" ReadOnly="true">
        <FlowDocument>
            <Paragraph FontSize="36">Hello, world!</Paragraph>
            <Paragraph FontStyle="Italic" TextAlignment="Left" FontSize="14" Foreground="Gray">Thanks to the RichTextBox control, this FlowDocument is completely editable!</Paragraph>
        </FlowDocument>
    </RichTextBox>

Upvotes: 1

Related Questions