How to bind multiple values to a single WPF TextBlock?
Asked Answered
A

4

260

I'm currently using the TextBlock below to bind the value of a property named Name:

<TextBlock Text="{Binding Name}" />

Now, I want to bind another property named ID to the same TextBlock.

Is it possible to bind two or more values to the same TextBlock? Can it be done with simple concatenation, like Name + ID and, if not, how else could this be approached?

Asterisk answered 31/3, 2010 at 12:32 Comment(0)
W
533

You can use a MultiBinding combined with the StringFormat property. Usage would resemble the following:

<TextBlock>
    <TextBlock.Text>    
        <MultiBinding StringFormat="{}{0} + {1}">
            <Binding Path="Name" />
            <Binding Path="ID" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

Giving Name a value of Foo and ID a value of 1, your output in the TextBlock would then be Foo + 1.

Note: This is only supported in .NET 3.5 SP1 and 3.0 SP2 or later.

Witting answered 31/3, 2010 at 12:42 Comment(5)
@Preet - I'm actually not certain if the '{}' is necessary in this case, I included it since it was used on the MSDN sample. In general however, it is needed as an escape sequence for the XAML parser to avoid confusion with the Binding markup extension.Witting
There is one side-affect to this. If you use this method in something like a DataGrid sorting behaviour unfortunately does not work. A more appropriate solution would be to create a read-only property in your model with the appropriate string format to bind against. Needless to say, this is a neat way to quickly format albeit a little verbose.Fulfil
you just need {} when the format string starts with the parameter {0}, it is not needed if the format string starts with a text. ex: "{}{0} + {1}" "Page {0} of {1}"Timeworn
It didn't work on a WPF project .Net 4.0 Visual Studio 2017.Constipate
@Patrick's solution worked for me. I could not get this to work. I had this error XamlParseException: A 'Binding' cannot be set on the 'Path' property of type 'Binding'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.Proverbs
E
172

I know this is a way late, but I thought I'd add yet another way of doing this.

You can take advantage of the fact that the Text property can be set using "Runs", so you can set up multiple bindings using a Run for each one. This is useful if you don't have access to MultiBinding (which I didn't find when developing for Windows Phone)

<TextBlock>
  <Run Text="Name = "/>
  <Run Text="{Binding Name}"/>
  <Run Text=", Id ="/>
  <Run Text="{Binding Id}"/>
</TextBlock>
Elsy answered 6/6, 2012 at 16:57 Comment(7)
This is a very handy approach to use when binding to several strings that are sourced as a DynamicResource as you can't use a MultiBinding with StringFormat for that.Icebound
I just tried this. It works, however every element (even geometry) that gets drawn (on a refresh) now blinks each tick for some reason. Going to try the other method.Izabel
This can get difficult if the text has to be localized because the order is hardcoded.Cenozoic
Another usage of this approach is applying different style per each bindingNumismatics
best answer for 2019Lubbi
This worked for me, though with one change. I had to add Mode=OneWay to my bindings. Maybe this is something specific to me using immutable data types.Proverbs
@Cenozoic That may not be an issue because we typically bind data not UI item itself and I don't think we translate user input data that might be in a database or entered by user.Necrosis
D
26

If these are just going to be textblocks (and thus one way binding), and you just want to concatenate values, just bind two textblocks and put them in a horizontal stackpanel.

    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Name}"/>
        <TextBlock Text="{Binding ID}"/>
    </StackPanel>

That will display the text (which is all Textblocks do) without having to do any more coding. You might put a small margin on them to make them look right though.

Disembowel answered 31/3, 2010 at 13:54 Comment(0)
S
13

Use a ValueConverter

[ValueConversion(typeof(string), typeof(String))]
public class MyConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return string.Format("{0}:{1}", (string) value, (string) parameter);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {

        return DependencyProperty.UnsetValue;
    }
}

and in the markup

<src:MyConverter x:Key="MyConverter"/>

. . .

<TextBlock Text="{Binding Name, Converter={StaticResource MyConverter Parameter=ID}}" />
Simonette answered 31/3, 2010 at 12:35 Comment(1)
Yes - this was written 6 years ago, and you're binding the "Name" as the first argument to the converter (called value in the code), and the ID (a string from the question) as the second argument.Simonette

© 2022 - 2024 — McMap. All rights reserved.