I have an external control which displays a layout formed from a label and an input control. My label requires special formatting (subscript) but it currently only supports direct text.
So my approach is to create a custom TextBlock
implementation, which exposes a new InlineContent
dependency property that, once set, converts the content and adds it to it's actual Inlines
collection.
For the layout control I add a custom DataTemplate
which binds the label content to the InlineContent
property of my custom text block.
ExtendedTextBlock.cs
:
private static void InlinesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is ExtendedTextBlock b)) return;
b.Inlines.Clear();
if (e.NewValue is InlineCollection collection)
b.Inlines.AddRange(collection);
if (e.NewValue is Span span)
b.Inlines.AddRange(span.Inlines);
if (e.NewValue is Run run)
b.Inlines.Add(run);
if (e.NewValue is string str)
b.Inlines.Add(new Run(str));
}
DataTemplate:
<DataTemplate>
<controls:ExtendedTextBlock InlineContent="{Binding}" />
</DataTemplate>
Label:
<dxlc:LayoutItem.Label>
<Span>
<Run>Right (R</Run>
<Run Typography.Variants="Subscript">R</Run>
<Run>)</Run>
</Span>
</dxlc:LayoutItem.Label>
This works fine for regular text (strings) but when I set a Span
as my label's content, then I get the following exception:
System.Windows.Markup.XamlParseException: 'Collection was modified; enumeration operation may not execute.' Inner Exception: InvalidOperationException: Collection was modified; enumeration operation may not execute.
This occurs in line b.Inlines.AddRange(span.Inlines)
. Why so? I don't understand which collection changes.
Binding directly to Text
does not work. Then I only see 'System.Documents.Text.Span` but not the span actually being rendered.