Reputation: 1620
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
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
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
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
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