New to Telerik UI for WPF? Download free 30-day trial

InlineUIContainer

RadRichTextBox provides you with the functionality of enclosing custom UI elements in its document. This is achieved with the help of a special type of inline document element called InlineUIContainer, which can wrap any object of type System.Windows.UIElement, e.g. a button, an image or even a media element or media player.

The InlineUIContainer is an inline element, so it should be placed in a Block that can contain inline elements (e.g. Paragraph).

Add UI Element to an InlineUIContainer

You can add any element that derives from the UIElement class inside the InlineUIContainer. To do that, simply wrap the desired element inside the tag of the InlineUIContainer in case you are defining it in XAML. If you are using code, use the UIElement property of the container. Here is a simple example with a Button.

In order to utilize the InlineUIContainer, you have to set its Height and Width explicitly (or use the constructor that takes a Size as a parameter). Otherwise, they will not be shown in the document.

Example 1: Add UI Element to an InlineUIContainer

<telerik:RadRichTextBox Name="radRichTextBox"> 
    <telerik:RadDocument> 
        <telerik:Section> 
            <telerik:Paragraph> 
                <telerik:InlineUIContainer Height="25" Width="70"> 
                    <Button Name="button" Content="Button" /> 
                </telerik:InlineUIContainer> 
            </telerik:Paragraph> 
        </telerik:Section> 
    </telerik:RadDocument> 
</telerik:RadRichTextBox> 

Example 1: Add UI Element to an InlineUIContainer

Section section = new Section(); 
Paragraph paragraph = new Paragraph(); 
InlineUIContainer container = new InlineUIContainer(); 
container.UiElement = new Button(); 
container.Height = 25; 
container.Width = 70; 
paragraph.Inlines.Add(container); 
section.Blocks.Add(paragraph); 
this.radRichTextBox.Document.Sections.Add(section); 
Dim _section As New Section() 
Dim _paragraph As New Paragraph() 
Dim container As New InlineUIContainer() 
container.UiElement = New Button() 
container.Height = 25 
container.Width = 70 
_paragraph.Inlines.Add(container) 
_section.Blocks.Add(_paragraph) 
Me.radRichTextBox.Document.Sections.Add(_section) 

Example 2 is a more complex example, which demonstrates how to implement a Button that inserts a MediaElement inside the RadRichTextBox's document.

Example 2: Add MediaElement on Button Click

private static Size defaultSize = new Size(900, 400); 
private void InsertMedia(Size size) 
{ 
    OpenFileDialog ofd = new OpenFileDialog(); 
    if (ofd.ShowDialog() == true) 
    { 
        Stream stream = ofd.File.OpenRead(); 
        MediaElement media = new MediaElement(); 
        media.SetSource(stream); 
        media.AutoPlay = true; 
        InlineUIContainer container = new InlineUIContainer() 
        { 
            UiElement = media 
        }; 
        if (size != Size.Empty) 
        { 
            container.Height = size.Height; 
            container.Width = size.Width; 
        } 
        this.radRichTextBox1.InsertInline(container); 
    } 
} 
private void buttonInsertVideo_Click(object sender, RoutedEventArgs e) 
{ 
    InsertMedia(defaultSize); 
} 
private void buttonInsertAudio_Click(object sender, RoutedEventArgs e) 
{ 
    InsertMedia(Size.Empty); 
} 
Private Shared defaultSize As New Size(900, 400) 
Private Sub InsertMedia(ByVal _size As Size) 
 Dim ofd As New OpenFileDialog() 
 If ofd.ShowDialog() = True Then 
  Dim _stream As Stream = ofd.File.OpenRead() 
  Dim media As New MediaElement() 
  media.SetSource(_stream) 
  media.AutoPlay = True 
  Dim container As New InlineUIContainer() With {.UiElement = media} 
  If _size <> Size.Empty Then 
   container.Height = _size.Height 
   container.Width = _size.Width 
  End If 
  Me.radRichTextBox1.InsertInline(container) 
 End If 
End Sub 
Private Sub buttonInsertVideo_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) 
 InsertMedia(defaultSize) 
End Sub 
Private Sub buttonInsertAudio_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) 
 InsertMedia(Size.Empty) 
End Sub 

Specifics

InlineUIContainer elements are not copyable.

The following scenarios are affected:

  • Drag-and-drop operation
  • Copy/paste operation
  • Update of the layout when the InlineUIContainer is in the header/footer
  • Print operation

The reason is that copying InlineUIContainer involves cloning of the internal UIElement, which cannot be handled in a generic way.

To enable copying of InlineUIContainers in your application, you can create a custom object, which can copy the UIElement inside the container. What you need to do is to inherit the InlineUIContainer class and override IsCopyable, CreateNewElementInstance(), CopyPropertiesFromOverride(). The container and its parts are copied in the CopyPropertiesFromOverride() method, so you should ensure that the override copies the UIElement inside the container as well.

Example 3: Implement CopyableInlineUIContainer for a Button as underlying UIElement

public class CopyableInlineUIContainer : InlineUIContainer 
{ 
    internal CopyableInlineUIContainer() 
    { 
 
    } 
 
    public CopyableInlineUIContainer(UIElement uiElement, Size size) 
        : base(uiElement, size) 
    { 
 
    } 
 
    public override bool IsCopyable 
    { 
        get 
        { 
            return true; 
        } 
    } 
 
    protected override DocumentElement CreateNewElementInstance() 
    { 
        return new CopyableInlineUIContainer(); 
    } 
 
    protected override void CopyPropertiesFromOverride(DocumentElement fromElement) 
    { 
        CopyableInlineUIContainer fromUIContainer = (CopyableInlineUIContainer) fromElement; 
        this.Width = fromUIContainer.Width; 
        this.Height = fromUIContainer.Height; 
 
        Button originalButton = (Button) fromUIContainer.UiElement; 
        this.UiElement = new Button() 
        { 
            Width = originalButton.Width, 
            Height = originalButton.Height, 
            Content = originalButton.Content.ToString() 
        }; 
    } 
} 
Public Class CopyableInlineUIContainer 
    Inherits InlineUIContainer 
 
    Friend Sub New() 
    End Sub 
 
    Public Sub New(ByVal uiElement As UIElement, ByVal size As Size) 
        MyBase.New(uiElement, size) 
    End Sub 
 
    Public Overrides ReadOnly Property IsCopyable As Boolean 
        Get 
            Return True 
        End Get 
    End Property 
 
    Protected Overrides Function CreateNewElementInstance() As DocumentElement 
        Return New CopyableInlineUIContainer() 
    End Function 
 
    Protected Overrides Sub CopyPropertiesFromOverride(ByVal fromElement As DocumentElement) 
        Dim fromUIContainer As CopyableInlineUIContainer = CType(fromElement, CopyableInlineUIContainer) 
        Me.Width = fromUIContainer.Width 
        Me.Height = fromUIContainer.Height 
        Dim originalButton As Button = CType(fromUIContainer.UiElement, Button) 
        Me.UiElement = New Button() With { 
            .Width = originalButton.Width, 
            .Height = originalButton.Height, 
            .Content = originalButton.Content.ToString() 
        } 
    End Sub 
End Class 

There is a very generic option for copying UIElement objects, which might help in most of the cases. However, have in mind that depending on the UI elements on which it will be invoked, the implementation might differ.

Example 4: Copy UI Element

public static UIElement Clone(this UIElement elementToClone) 
{ 
    if (elementToClone != null) 
    { 
        string elementXaml = XamlWriter.Save(elementToClone); 
        StringReader stringReader = new StringReader(elementXaml); 
 
        XmlReader xmlReader = XmlTextReader.Create(stringReader, new XmlReaderSettings()); 
        return (UIElement)XamlReader.Load(xmlReader); 
    } 
 
    return null; 
} 
<Extension()> 
Public Shared Function Clone(ByVal elementToClone As UIElement) As UIElement 
    If elementToClone IsNot Nothing Then 
        Dim elementXaml As String = XamlWriter.Save(elementToClone) 
        Dim stringReader As StringReader = New StringReader(elementXaml) 
        Dim xmlReader As XmlReader = XmlTextReader.Create(stringReader, New XmlReaderSettings()) 
        Return CType(XamlReader.Load(xmlReader), UIElement) 
    End If 
 
    Return Nothing 
End Function 

Import/Export InlineUIContainers

Most features that RadRichTextBox provides are also supported in the format providers that it uses for export and import.

For more information on Import/Export, please refer to this topic.

However, as the UIElement class is a WPF specific concept, some format providers support them in a non-standard way and others do not support them at all.

Exporting InlineUIContainers:

Different approaches have been adopted when it comes to exporting inline UI containers via the format providers:

  • XamlFormatProvider: Inline UI containers are serialized as expected, thus ensuring lossless export in simple cases, e.g. when a button is in the container. Custom attached properties may not be exported.

  • HtmlFormatProvider: The inline UI containers are serialized as XAML and are included in the HTML as comments. If the user handles the InlineUIContainerExporting event, they can provide their own implementation for the export of the UI elements by accessing the properties of the InlineUIContainerExportingEventArgs and setting the ones they need. The CommentContent contains the XAML serialization and the HtmlContent string property can be set to the desired user-defined HTML equivalent of the UI element. It will appear when the page is rendered outside RadRichTextBox. The UI element can also be omitted from the document altogether.

WPF RadRichTextBox Inline UI Container

  • DocxFormatProvider: All InlineUIContainers are ignored as the Microsoft Word concept of controls is quite different.

  • RtfFormatProvider: All InlineUIContainers are ignored as the RTF standard does not have a concept for similar elements.

  • PdfFormatProvider: The InlineUIContainers are taken a snapshot of and included in the export. If you like, you can prevent that by setting the InlineUIContainersExportMode property of the provider to None. WPF RadRichTextBox Inline UI Containers Export Mode None

Importing InlineUIContainers

There are some differences between the format providers when it comes to importing InlineUIContainers, too.

  • XamlFormatProvider: All inline UI containers are deserialized and imported.

  • DocxFormatProvider: There cannot be any inline UI containers in DOCX, as they are not exported in the first place.

  • RtfFormatProvider: There cannot be any inline UI containers in RTF, as they are not exported in the first place.

  • PdfFormatProvider: PDF import is currently not supported.

See Also

In this article