Why is the ClearTextButton icon showing as a letter r when defining TextBlock style?

118 Views Asked by At

Using Visual Studio 2022, .NET 6, WPF (with MVVM), Mahapps.Metro (+IconPacks), C#.

I'm using Mahapps.Metro and I defined a style for the ComboBox so that it shows a clear text button.

<Style TargetType="ComboBox" x:Key="{x:Type ComboBox}"
       BasedOn="{StaticResource MahApps.Styles.ComboBox}">
    <Setter Property="FontFamily" Value="Segoe UI"/>
    <Setter Property="FontSize" Value="9"/>
    <Setter Property="mah:TextBoxHelper.ClearTextButton" Value="True"/>
</Style>

This seems to work perfectly...

ComboBox with "X" clear button in designer.

However... When I also define a style for TextBlock then the X icon is suddenly shown as the letter 'r'.

ComboBox with "r" clear text button in designer.

The XAML for my ComboBox is quite simple...

<ComboBox x:Name="CustomerCustomerCategoryComboBox"
          Grid.Column="2" Grid.Row="2"
          MinWidth="100"
          Grid.ColumnSpan="3"

I'm completely baffled to be honest. I have no clue whatsoever as to what causes this behaviour. Has someone else experienced this or, better even, know what I can do to solve this?

I've tried all sorts of things... removing the TexBlock style solves it obviously but that way I lose the style for all my other TexBlocks. Tried playing around with the Style settings, googled my problem with several keywords and phrases but I seem to be the only one?

1

There are 1 best solutions below

0
thatguy On

As you can see from the default style for the clear button here , it uses:

In other words, a special font is used that has symbols instead of letters and r is the cross symbol.

In the live element tree you can see that the clear button uses a TextBlock internally.

Visual element tree showing the ComboBox, the clear button and its TextBlock.

Your style is a so-called implicit style, meaning it specifies the control type itself as x:Key. Therefore it will apply to all TextBlocks in scope that do not explicitly set a different style. This also applies to the TextBlocks that displays the cross symbol for the clear button. You effectively override the default font family.

Overriding control styles globally is not favorable, especially if you use external libraries that depend on default framework styles.

  • You should either create an explicit TextBlock style and apply it where you really need it or create an implicit style in a limited local scope (Resources of a view or control) where you can be sure that it does not intefere with other styles.
  • Doing it the other way around - creating a local implicit style that reverts the global style might be brittle as you cannot be sure how a TextBlock nested deep inside a control template is actually defined (without investigating the external code as well each time) and it might change in the future, too. Plus, keeping track of these implementation details is hard. In libraries that are not open source, checking the source is not even an option.
  • Copying and adapting the control template as workaround would be an overkill.

As a potential quick workaround, you could use the fact, that the TextBoxHelper also provides a property ButtonContentTemplate for specifying a content template, where you can remove the effects of your custom TextBlock style. However, this approach has the same issues as stated above, maintenance and side effects welcome in the long run.

<Style TargetType="ComboBox" x:Key="{x:Type ComboBox}"
       BasedOn="{StaticResource MahApps.Styles.ComboBox}">
   <Setter Property="FontFamily" Value="Segoe UI"/>
   <Setter Property="FontSize" Value="9"/>
   <Setter Property="mah:TextBoxHelper.ClearTextButton" Value="True"/>
   <Setter Property="mah:TextBoxHelper.ButtonContentTemplate">
      <Setter.Value>
         <DataTemplate>
            <TextBlock Text="{Binding Content, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
                       FontFamily="{Binding (mah:TextBoxHelper.ButtonFontFamily), RelativeSource={RelativeSource AncestorType={x:Type Button}}}"/>
         </DataTemplate>
      </Setter.Value>
   </Setter>
</Style>