Do not override DataTemplate for System.String

Default template for System.String is used whenever you create a control with Content of type String. E.g. <Label Content="foo" /> or <Label>foo</Label>. Overriding it may look like a good idea in some cases, but it causes bad side effects. Don't do that.

<!-- Danger! Do not do this at home! -->
<DataTemplate DataType="{x:Type system:String}">
    <TextBlock Text="{Binding}" />

Here's a set of labels rendered with and without string data template override:

The labels come from the following XAML:

<StackPanel Orientation="Vertical">
    <Label>Normal Text</Label>
    <Label>Access _Text</Label>
    <Label ContentStringFormat="Formatted {0}">Text</Label>
    <Label ContentStringFormat="Formatted Access {0}">_Text</Label>

MainWindow.xaml Full code

The overriden template does not convert underscores to keyboard shortucts, and does not respect ContentStringFormat. This is because ContentPresenter class (ContentPresenter.cs) uses not one, but four different templates to render strings: StringContentTemplate, AccessTextContentTemplate, FormattingStringContentTemplate and FormattingAccessTextContentTemplate. AccessText is a less famous brother of TextBlock that converts underscores into keyboard shortcuts.

How did I find out about this? The hard way. I was looking to the solution to the implicit TextBlock style overriding all TextBlocks in the application. In this StackOverflow question the answer suggests to override data template for String, and I followed it. In a couple of days QA told me that now we have underscores in the text of most of our buttons, so I had to issue an emergency fix. As they say, smart people learn from the mistakes of others. Less smart people learn from their own mistakes.


Questions? Comments?
Drop me a line