What is the WPF XAML Data Binding equivalent of String.Format?
Asked Answered
F

5

31

Or, to be more clear, how can I format a block of text (in my case, to be included within a tooltip) such that some portions of the text come from bound values.

In plain C# I would use:

_toolTip.Text = string.Format("{1:#0}% up, {2:#0}% down",
    Environment.NewLine, percentageOne, percentage2);

However the WPF XAML markup for a Text property seems able to contain only a single binding. The curly braces gave me high hopes, but this isn't possible:

<Element>
  <Element.Tooltip>
    <!-- This won't compile -->
    <TextBlock Text="{Binding Path=PercentageOne}% up, {Binding Path=PercentageTwo}% down"/>
  </Element.Tooltip>
</Element>

I read that the Run.Text property is not a dependency property and can therefore not be bound.

Is there a way I can perform this formatting in XAML?

Fronde answered 15/1, 2009 at 14:52 Comment(0)
C
45

You can use MultiBinding + StringFormat (requires WPF 3.5 SP1):

<TextBox.Text>
    <MultiBinding StringFormat="{}{1:#0}% up, {2:#0}% down">
      <Binding Path="PercentageOne" />
      <Binding Path="PercentageTwo"/>
    </MultiBinding>
</TextBox.Text>

Regarding Run.Text - you can't bind to it but there are some workarounds:

Cleanlimbed answered 15/1, 2009 at 15:8 Comment(3)
awesome, didn't know about that new feature. Do you know what the empty squiglies at the beginning of the string represents?Warthog
{} is necessary to tell WPF to not treat {something} as a markup extension.Cleanlimbed
Cheers aku. Unfortunately I'm not targeting SP1 so will have to kludge this one. Still, I think this is the most elegant answer so I've given it to you.Fronde
V
11

I would split into multiple textblocks, binding each one with the StringFormat={0:P} in the binding as such:

<TextBox Text="{Binding Something, StringFormat=\{0:P\}}" />

See this post for examples:Lester's WPF Blog on StringFormat

Checkout VS2010 - The binding from properties includes formatting in the options.

Vallecula answered 9/2, 2010 at 15:45 Comment(0)
S
3

If you're using 3.5 SP1, Aku's answer is the way to go. If you're not, you can use the FormatConverter from my WPF Converters library.

Sixtyfourmo answered 15/1, 2009 at 16:34 Comment(1)
Thanks Kent, these look useful and I'll check them out today. BTW the formatting on the codeplex page you've listed doesn't look quite right towards the end of code samples (in Chrome on WinXP at least).Fronde
W
2

As far as I know, WPF doesn't do what you want. You do have a much more powerful (albeit more involved) solution.

Take a look at the IValueConverter interface.

MSDN HowTo link here

EDIT

Based on aku's answer, and your assertion that you can't use 3.5 SP1, here's an alternative.

Take a look at Phil Haack's recent series of posts on string formatting:

Create a ValueConverter as that takes the format as a property. You should then be able to bind your data object and have it format based on your defined format (using property name instead of position).

Warthog answered 15/1, 2009 at 15:8 Comment(1)
Hi Michael. Thanks, but I was hoping to do something more declarative in the XAML rather than having to write a .NET type specifically catering to my requirement. It wouldn't be reusable outside of this context in the way that String.Format is reusable.Fronde
P
2

The way I've solved this in the past is actually to break the TextBlock you have in your listing up into several TextBlocks. Try something like this:

<Element>
  <Element.Tooltip>
    <StackPanel Orientation="Horizontal">
      <TextBlock Text="{Binding Path=PercentageOne}"/>
      <TextBlock Text="% up, "/>
      <TextBlock Text="{Binding Path=PercentageTwo}"/>
      <TextBlock Text="% down"/>
    </StackPanel>
  </Element.Tooltip>
</Element>

Alternately you can create something like a StringFormatConverter, which could take the format string as a parameter, and use a MultiBinding to pass it the parameters. See this link for MultiBindings:

MultiBinding Info

And this one for info on converters:

Converters Info

You can pretty easily imagine a converter that takes "object[] values" instead of "object value" as it's first parameter, and passes those on to the Format function.

Pren answered 15/1, 2009 at 15:14 Comment(3)
increasing number of visuals can harm performance, also this markup can work different when text overflow occursCleanlimbed
Thanks for the answer. I'd considered the StackPanel approach but it seems a little clunky and I was hoping for something better. Also, as aku says, it wouldn't wrap neatly. Unfortunately I'm not using SP1 so can't using MultiBinding.Fronde
A WrapPanel would solve the wrapping issue in lieu of a StackPanelKrenek

© 2022 - 2024 — McMap. All rights reserved.