Search code examples
wpfxamllayoutdata-binding

Vertical alignment of Label inside TextBlock is wrong


In a WPF popup window that I display to the user I want to put a text that is bound to a variable inside a block of text. I've tried to do so by putting a <Label> inside a <TextBlock>. However, this leads to alignment problems, see markup and picture below. I wonder how I can get the text in the Label to align vertically with the text in the TextBlock, or if there is a better solution?

I could put the entire text in a variable, but then I don't know how to get <Bold> formatting for part of the text.

<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap"
 VerticalAlignment="Top" Height="99" Width="339" Grid.RowSpan="3">
    The user is <Bold>responsible</Bold> for 
    <Bold><Label Content="00" Padding="0"/></Bold> vehicles
</TextBlock>

Wrong alignment of label inside TextBlock.


Solution

  • You can use the Run inline element for data binding text.

    Starting in the .NET Framework 4, the Text property of the Run object is a dependency property, which means that you can bind the Text property to a data source.

    It also has properties for styling the text, like FontWeight, no need for <Bold> here.

    <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap"
     VerticalAlignment="Top" Height="99" Width="339" Grid.RowSpan="3">
        The user is <Bold>responsible</Bold> for 
        <Run Text="{Binding YourProperty}" FontWeight="Bold"/> vehicles
    </TextBlock>
    

    The result looks like this:

    Text with databound run.


    As a general note on the issue: The elements inside TextBlock should be inline elements. Here is an article that has links to other inline elements that could be useful to you, like span that allows for grouping other inline elements and applying styles or to them.

    WPF has two fundamental base types, UIElement and ContentElement. While a TextBlock and Label are UIElements, the content of TextBlock are inlines, which are ContentElements. That is why the alignment is off, they serve very different purposes. You can read up more on the differences and concepts here:

    • Base Element APIs in WPF Classes
    • UIElement

      UIElement is a base class for WPF core level implementations building on Windows Presentation Foundation (WPF) elements and basic presentation characteristics.

    • ContentElement

      Provides a WPF core-level base class for content elements. Content elements are designed for flow-style presentation, using an intuitive markup-oriented layout model and a deliberately simple object model.

    • Flow Document Overview