How to make all text upper case / capital?
Asked Answered
N

8

41

I want all texts in TextBlock, Label, MenuItem.Header to be displayed in upper case. The strings are taken from a ResourceDictionary e.g.:

<TextBlock Text="{StaticResource String1}"/>
<MenuItem Header="{StaticResource MenuItemDoThisAndThat}"/>

etc. (also for Label and other controls)

I cannot use a value converter because there is no binding. I don't want to make the strings upper case in the dictionary itself.

Ninanincompoop answered 19/11, 2009 at 10:54 Comment(0)
T
38

You still can use a converter, just set the textvalue in the source of the binding :

<TextBlock Text="{Binding Source={StaticResource String1},  Converter ={StaticResource myConverter}}"/>
Titanism answered 19/11, 2009 at 11:32 Comment(2)
Any solution for when you'd like to add this uppercase converter to the Style? If you do this within the Setter, it will be overwritten if you try to bind to the Text property later in XAML. It appears there'd be no choice but to add this converter per-instance.Baseball
i need to upper case string without using converter. is there any possible to acheive it? @TitanismSyrupy
T
44

I think this will work for you

<TextBlock Text='{StaticResource String1}' Typography.Capitals="AllPetiteCaps"/>

For font capitals enumerations https://msdn.microsoft.com/en-us/library/system.windows.fontcapitals(v=vs.110).aspx

Translator answered 20/1, 2016 at 6:33 Comment(5)
This produces text smaller than the font size.Keilakeily
<TextBlock Text='{StaticResource String1}' Typography.Capitals="AllPetiteCaps"/> This will make it same size as text wasEmpathize
I should also mention that AllPetiteCaps will work not for all fonts: https://mcmap.net/q/392290/-wpf-xaml-typography-capitals-seems-to-have-no-effectEmpathize
looks like you have the right idea here are all the other options available msdn.microsoft.com/en-us/library/…Theology
Updated answer.Translator
T
38

You still can use a converter, just set the textvalue in the source of the binding :

<TextBlock Text="{Binding Source={StaticResource String1},  Converter ={StaticResource myConverter}}"/>
Titanism answered 19/11, 2009 at 11:32 Comment(2)
Any solution for when you'd like to add this uppercase converter to the Style? If you do this within the Setter, it will be overwritten if you try to bind to the Text property later in XAML. It appears there'd be no choice but to add this converter per-instance.Baseball
i need to upper case string without using converter. is there any possible to acheive it? @TitanismSyrupy
D
32

Rather than using a converter, you can use the tag CharacterCasing in a TextBox but in your case, it doesn't work on a TextBlock.

<TextBox CharacterCasing="Upper" Text="{StaticResource String1}" />
Dripstone answered 7/6, 2011 at 16:35 Comment(5)
TextBlock does not have a CharacterCasing attribute - TextBox does though.Einsteinium
msdn.microsoft.com/fr-fr/library/…Dripstone
Another example of "peer review" gone wrong. 28 votes? Not only does it not address OP question regarding TextBlock, but as vaughan points out, wont workDowry
How does this have 22 upvotes. As previous comment states this is nothing to do with the OP.Newfashioned
As the documentation points out, CharacterCasing only affects letters which were typed in, so it wouldn't even achieve the intended effect on a TextBoxLigni
G
14

To complete Peter's answer (my edit has been rejected), you can use a converter like this:

C#:

public class CaseConverter : IValueConverter
{    
    public CharacterCasing Case { get; set; }

    public CaseConverter()
    {
        Case = CharacterCasing.Upper;
    }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var str = value as string;
        if (str != null)
        {
            switch (Case)
            {
                case CharacterCasing.Lower:
                    return str.ToLower();
                case CharacterCasing.Normal:
                    return str;
                case CharacterCasing.Upper:
                    return str.ToUpper();
                default:
                    return str;
            }
        }
        return string.Empty;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

XAML:

<TextBlock Text="{Binding Source={StaticResource String1}, Converter ={StaticResource myCaseConverter}}"/>
Glassful answered 24/4, 2015 at 7:35 Comment(3)
Why use a seperate Case property ? Cant we use the parameter to specify upper or lower ?Scintillate
Yes, to have a more versatile converter. You can change the case property in you XAML: <local:CaseConverter Case="Lower" x:Key="CaseConverter"/>Glassful
I think code has one small mistake. The line: if (value != null) should be: if (str != null)Selfassured
S
8

I created an attached property and converter for this. You probably already have the converter, so replace my reference to CaseConverter to whatever implementation you have.

The attached property is just a boolean that you set if you want it to be uppercase (you could obviously extend this to instead be an enumerable for a selection of styles). When the property changes, it rebinds the TextBlock's Text property as needed, adding in the converter.

A little more work might need to be done when the property is already bound - my solution assumes it's a simple Path binding. But it may need to also duplicate the source, etc. However I felt this example is enough to get my point across.

Here's the attached property:

public static bool GetUppercase(DependencyObject obj)
    {
        return (bool)obj.GetValue(UppercaseProperty);
    }

    public static void SetUppercase(DependencyObject obj, bool value)
    {
        obj.SetValue(UppercaseProperty, value);
    }

    // Using a DependencyProperty as the backing store for Uppercase.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty UppercaseProperty =
        DependencyProperty.RegisterAttached("Uppercase", typeof(bool), typeof(TextHelper), new PropertyMetadata(false, OnUppercaseChanged));

    private static void OnUppercaseChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        TextBlock txt = d as TextBlock;

        if (txt == null) return;

        var val = (bool)e.NewValue;

        if (val)
        {
            // rebind the text using converter
            // if already bound, use it as source

            var original = txt.GetBindingExpression(TextBlock.TextProperty);

            var b = new Binding();

            if (original != null)
            {
                b.Path = original.ParentBinding.Path;
            }
            else
            {
                b.Source = txt.Text;
            }

            b.Converter = new CaseConverter() { Case = CharacterCasing.Upper };


            txt.SetBinding(TextBlock.TextProperty, b);
        }
    }
Slipperwort answered 25/3, 2013 at 13:7 Comment(2)
Kind of an interesting concept, wrapping a converter in a behavior. What do you gain by that, though? You're writing about the same amount of xaml (attached property vs. just converter), but you lose flexibility: You're limited to textblock instead of any string. If you could replace the converter altogether, that might make more sense imo, but then how would you keep the binding? I think just a converter is the better way to go here.Capitulate
You can put this in a style, and have it apply to all textboxes, presumably.Cohen
R
3

This does not strictly answer the question but does provide a trick to cause the same effect.

I believe many finding their way here are looking how to do this with a style. TextBlock is a bit tricky here because it is not a Control but a FrameworkElement and therefore you can not define a Template to do the trick.

The need to use all uppercase text is most likely for headings or something like that where use of Label is justified. My solution was:

<!-- Examples of CaseConverter can be found in other answers -->

<ControlTemplate x:Key="UppercaseLabelTemplate" TargetType="{x:Type Label}">
    <TextBlock Text="{TemplateBinding Content, Converter={StaticResource CaseConverter}}" />
</ControlTemplate>

<Style x:Key="UppercaseHeadingStyle"
       TargetType="{x:Type Label}">
    <Setter Property="FontSize" Value="20" />
    <Setter Property="FontWeight" Value="Bold" />
    <Setter Property="Template" Value="{StaticResource UppercaseLabelTemplate}" />
</Style>

<!-- Usage: -->
<Label Content="Header" Style="{StaticResource UppercaseHeadingStyle}" />

Note that this does disable some of the default behavior of Label, and works only for text, so I would not define this as default (no one probably wants all labels uppercase anyway). And of course you must use Label instead of TextBlock when you need this style. Also I would not use this inside of other templates, but only strictly as a topic style.

Ramulose answered 14/8, 2015 at 7:29 Comment(0)
B
1
    public class StaticResourceToUpperExtension : StaticResourceExtension
    {
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            var resource = base.ProvideValue(serviceProvider);
            if (resource is string str)
                return str.ToUpper();
            return resource;
        }

        public StaticResourceToUpperExtension() : base() { }
        public StaticResourceToUpperExtension(object resourceKey) : base(resourceKey) { }

    }
    <Grid>
        <FrameworkElement.Resources>
            <sys:String x:Key="String1">any text</sys:String>
        </FrameworkElement.Resources>
        <TextBlock Text="{local:StaticResourceToUpper String1}"/>
    </Grid>
Bosket answered 3/6, 2021 at 11:56 Comment(0)
M
-4

You can case all input into TextBox controls with the following property:

<TextBox CharacterCasing="Upper"

To apply to all TextBox controls in the entire application create a style for all TextBox controls:

<Style TargetType="{x:Type TextBox}">
  <Setter Property="CharacterCasing" Value="Upper"/>
</Style>
Mawkin answered 21/8, 2012 at 10:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.