Marcel
Marcel

Reputation: 1074

Providing a generic controlbar for my custom RichTextBox

I created a custom RichTextBox and want to provide a short and easy way to add EditingCommands on the client-side, e.g. Bold, Italic, Underline: enter image description here

So, I just added this property in my MyRichTextBox and bound it to an ItemsControl in Generic.xaml

public ItemCollection EditingCommands { get; } = new DataGrid().Items;

The usage in the client looks really straight-forward ;-):

<c:MyRichTextBox Text="{Binding Text, Mode=TwoWay}">
    <c:MyRichTextBox.EditingCommands>
        <Button Content="B" FontWeight="Bold" ToolTip="Bold: Ctrl+B" Width="20"
                Command="EditingCommands.ToggleBold" />
        <Button Content="I" FontStyle="Italic" ToolTip="Italic: Ctrl+I" Width="20"
                Command="EditingCommands.ToggleItalic" />
        <Button ToolTip="Underline: Ctrl+U" Width="20"
                Command="EditingCommands.ToggleUnderline">
            <TextBlock TextDecorations="Underline" Text="U" Padding="0" Margin="0" />
        </Button>
    </c:MyRichTextBox.EditingCommands>
</c:MyRichTextBox>

But I want to reuse the control several times, so I would like to set the EditingCommands by a style, e.g.

<Style x:Key="MyRichTextBoxStyle" TargetType="{x:Type c:MyRichTextBox}">
    <Setter Property="EditingCommands">
        <Setter.Value>
            <Button Content="B" FontWeight="Bold" ToolTip="Bold: Ctrl+B" Width="20"
                Command="EditingCommands.ToggleBold" />
            <Button Content="I" FontStyle="Italic" ToolTip="Italic: Ctrl+I" Width="20"
                Command="EditingCommands.ToggleItalic" />
            <Button ToolTip="Underline: Ctrl+U" Width="20"
                Command="EditingCommands.ToggleUnderline">
                <TextBlock TextDecorations="Underline" Text="U" Padding="0" Margin="0" />
            </Button>
        </Setter.Value>
    </Setter>
</Style>

But that's impossible because EditingCommands is not a dependency property. As well as converting to dependency property is not suitable with the type ItemCollection.

Actually I'm wondering: Is that the right track for the main goal at all? Putting Buttons into a ItemCollection? Has anyone a better idea? Maybe ButtonModels in concert with a DataTemplate?

Upvotes: 0

Views: 131

Answers (1)

mm8
mm8

Reputation: 169160

Is that the right track for the main goal at all? Putting Buttons into a ItemCollection? Has anyone a better idea?

You could create your own custom collection and add a dependency property of this type to your custom RichTextBox class:

public class CustomItemCollection : ObservableCollection<UIElement>
{
}

public class MyRichTextBox : RichTextBox
{
    public static readonly DependencyProperty EditingCommandsProperty =
         DependencyProperty.Register("EditingCommands", typeof(CustomItemCollection),
         typeof(MyRichTextBox));

    public CustomItemCollection EditingCommands
    {
        get { return (CustomItemCollection)GetValue(EditingCommandsProperty); }
        set { SetValue(EditingCommandsProperty, value); }
    }
}

You can then set the property in a Style setter:

<Style x:Key="MyRichTextBoxStyle" TargetType="{x:Type c:MyRichTextBox}" x:Shared="False">
    <Setter Property="EditingCommands">
        <Setter.Value>
            <c:CustomItemCollection>
                <Button Content="B" FontWeight="Bold" ToolTip="Bold: Ctrl+B" Width="20" Command="EditingCommands.ToggleBold" />
                <Button Content="I" FontStyle="Italic" ToolTip="Italic: Ctrl+I" Width="20" Command="EditingCommands.ToggleItalic" />
                <Button ToolTip="Underline: Ctrl+U" Width="20" Command="EditingCommands.ToggleUnderline">
                    <TextBlock TextDecorations="Underline" Text="U" Padding="0" Margin="0" />
                </Button>
            </c:CustomItemCollection>
        </Setter.Value>
    </Setter>
</Style>

Displaying the buttons is a matter of modifying the template of the MyRichTextBox class to include an ItemsControl that binds to the EditingCommands property, e.g.:

<c:MyRichTextBox>
    <c:MyRichTextBox.Style>
        <Style TargetType="c:MyRichTextBox" BasedOn="{StaticResource MyRichTextBoxStyle}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="c:MyRichTextBox">
                        <StackPanel>
                            <ItemsControl ItemsSource="{TemplateBinding EditingCommands}" HorizontalAlignment="Right">
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <StackPanel Orientation="Horizontal" />
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                            </ItemsControl>
                            <RichTextBox />
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </c:MyRichTextBox.Style>
</c:MyRichTextBox>

Upvotes: 1

Related Questions