Reputation: 12695
After quite some search and reading other questions & posts, I was not able to find how to solve this. Note: I'm relatively new to WPF (not to binding in general).
Here's what I'm after:
Here's an excerpt of what I'm playing with:
<!-- in Window resources -->
<help:AllCapsStringConverter x:Key="AllCaps"/>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Brown" />
<Setter Property="Text">
<Setter.Value>
<Binding>
<Binding.Converter>
<help:AllCapsStringConverter />
</Binding.Converter>
<!-- also tried adding:
<Binding.RelativeSource>
<RelativeSource Mode="Self" />
</Binding.RelativeSource>
-->
</Binding>
<!-- also tried with:
<Binding Converter="{StaticResource AllCaps}"/>
<Binding Path="Text" Converter="{StaticResource AllCaps}"/>
-->
</Setter.Value>
</Setter>
</Style>
<!-- in Window content -->
<TextBlock Text="{x:Static resx:MyResources.MyTitle}" />
Here's the value converter, which on its own has proved to be working:
class AllCapsStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && value is string)
{
return ((string)value).ToUpper();
}
else
{
return value;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
TextBlocks get the foreground color, but no conversion kicks in.
I was able to apply the converter locally to the single TextBlock, but I don't want to apply that to all TextBlocks around the window:
<TextBlock>
<TextBlock.Text>
<Binding Source="{x:Static resx:MyResources.MyTitle}"
Converter="{StaticResource AllCaps}"/>
</TextBlock.Text>
</TextBlock>
<!-- which is the same as -->
<TextBlock Style="{StaticResource CustomerInfoTitleStyle}"
Text="{Binding Source={x:Static resx:MyResources.MyTitle}, Converter={StaticResource AllCaps}}" />
Upvotes: 0
Views: 2511
Reputation: 71
Your converter is not working because your TextBlock
is overriding the Text
property of the Style
, which includes the converter you have added to the binding.
For example:
<Grid.Resources>
<Style x:Key="MyTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Text" Value="You won't see this."></Setter>
</Style>
</Grid.Resources>
<TextBlock Text="You will see this." Style="{StaticResource MyTextBlockStyle}"/>
Hopefully from the above you can see why your approach is not working.
A better solution would just be to set the value of Text
with the value converter on the TextBlock
, rather than in the Style
.
If you don't want to do that, one common cheat you could use to get around this could be to bind the TextBlock's Text property to the Tag property, like so:
<Grid.Resources>
<local:AllCapsConverter x:Key="AllCaps"/>
<Style x:Key="MyTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Text" Value="{Binding Tag, RelativeSource={RelativeSource Self}, Converter={StaticResource AllCaps}}"/>
</Style>
</Grid.Resources>
<TextBlock Tag="You will see this." Style="{StaticResource MyTextBlockStyle}"/>
I have a strong dislike of this approach, but it does get you what you want. I would prefer you just use the converter when you set the binding on the TextBlock
.
lukegv's approach is another alternative. However, there is no need to use a Label
, as you are overriding the template and (similar to my example above) you are just binding to the Content
property of the Label
. You could just as easily get what you need from a ContentControl
.
<Grid.Resources>
<local:AllCapsConverter x:Key="AllCaps"/>
<Style x:Key="MyContentControl" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource AllCaps}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<ContentControl Style="{StaticResource MyContentControl}" Content="You will see this too!"/>
I'm not a particularly huge fan of this idea either though, as you lose access to all the other TextBlock
properties. For example, if I wanted to set the FontWeight
property of my TextBlock
then I would be stuffed.
Upvotes: 2
Reputation: 14493
Try to use a 'Label' and build a template, because a 'TextBlock' is not a control.
<Style x:Key="AllCapsLabel" TargetType="{x:Type Label}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<TextBlock Foreground="Brown" Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource AllCaps}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And use it this way:
<Label Style="{StaticResource AllCapsLabel}" Content="whatever you want" />
If the content is plain text (aka a 'String'), the text should always be uppercase.
Upvotes: 0