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?
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:
- http://fortes.com/2007/03/20/bindablerun/
- http://paulstovell.net/blog/index.php/attached-bindablerun/
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.
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.
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.
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:
- Fun With Named Formats, String Parsing, and Edge Cases
- Named Formats Redux
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).