Building a Custom Toolbar for the WPF HTML Editor

Yuki works at a Japanese ERP vendor in Osaka. Her team has just landed a redesign of the Sales Order module, and one of the visible pieces is a small notes panel that sits inside every order line. The product owner is firm: the notes panel must feel embedded, not bolted on. A full WYSIWYG toolbar with thirty buttons looming over a four-line text field is exactly the kind of thing he wants to avoid.

The requirement is clean: four commands only - Bold, Italic, Bullet List, and Hyperlink. Same height as the surrounding form labels. Same accent color as the rest of the new design system. Everything else should disappear.

Compact four-button toolbar embedded inside an ERP sales order row

Yuki has been using the WpfHtmlEditor for the document-editor screen elsewhere in the product, so she knows it has powerful built-in toolbars. The challenge is that for this embedded scenario she doesn't want any of them visible. She digs into the API and finds two things she needs: the built-in Toolbar1 and Toolbar2 are public properties on the editor (so she can collapse them), and every individual factory button is reachable through editor.ToolbarItemOverrider.ToolbarItems (so she can re-parent the four she wants).

Her XAML defines her own bare ToolBar directly above the editing surface, sized exactly to her design tokens.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <ToolBar x:Name="CompactToolbar" Grid.Row="0" Height="28"
             Background="{StaticResource Form.Accent}" />
    <wpfHtmlEditor:WpfHtmlEditor x:Name="NotesEditor" Grid.Row="1"
                                 Loaded="NotesEditor_OnLoaded" />
</Grid>

The Loaded handler is where the actual surgery happens. Yuki collapses both built-in toolbars and then moves only the four buttons she needs into CompactToolbar.

private void NotesEditor_OnLoaded(object sender, RoutedEventArgs e)
{
    NotesEditor.Toolbar1.Visibility = Visibility.Collapsed;
    NotesEditor.Toolbar2.Visibility = Visibility.Collapsed;

    var items = NotesEditor.ToolbarItemOverrider.ToolbarItems;
    Adopt(items.Bold);
    Adopt(items.Italic);
    Adopt(items.UnOrderedList);
    Adopt(items.Hyperlink);
}

private void Adopt(Control factoryControl)
{
    if (factoryControl.Parent is ItemsControl previousHost)
        previousHost.Items.Remove(factoryControl);

    CompactToolbar.Items.Add(factoryControl);
}

The buttons she moves are the actual factory ToggleButton and Button instances - not copies. Every wired click handler, every tooltip, every bit of context-sensitive state highlighting that the editor maintains internally still works. When the caret sits inside bold text, her adopted Bold toggle still lights up. The visual container changed; the wiring didn't.

Four factory buttons relocated into the slim compact ToolBar with the built-in strips hidden

The product owner reviews the result with her at the next demo. "That is what I had in my head," he says, and signs it off. A week later he asks Yuki to do the same trick on the Customer Contacts screen, this time with five buttons. She copy-pastes the helper method, swaps the buttons in the NotesEditor_OnLoaded handler, and it's done before lunch.

  • editor.Toolbar1.Visibility and editor.Toolbar2.Visibility hide the built-in toolbar strips.
  • editor.ToolbarItemOverrider.ToolbarItems exposes every factory button so you can re-parent it into your own ToolBar.
  • Re-parented factory buttons keep their click handling and context-sensitive state intact.
Last updated on May 12, 2026