Search code examples
c#wpfxamlcontroltemplatetemplatebinding

WPF TemplateBinding Concatenate String for Value


I want to add a Custom Property (via a Dependency Property) to my custom ToggleButton Template. Now i want to have the value of the containing Label (as a placeholder for future implementation) to be a concatenated value of, say "Hello " and the actual Property Value.

Without the concatenation it works fine (displaying "Warrior" on the Label)

But when i try to set the label as a concatenation the xaml doesnt compile anymore.

<Label Content="Hello {TemplateBinding local:HeroClassCheckbox.HeroClass}"/>

How can i achieve this?

The Rest of the Code:

My .xaml

<Window.Resources>
    <ResourceDictionary>
        <Style x:Key="HeroClassCheckbox" TargetType="ToggleButton">
            <Setter Property="Content" Value="Green" />
            <Setter Property="local:HeroClassCheckbox.HeroClass" Value="NoClass"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Label Content="{TemplateBinding local:HeroClassCheckbox.HeroClass}"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
</Window.Resources>
<Grid>
    <ToggleButton Width="150" Height="50" local:HeroClassCheckbox.HeroClass="Warrior" Style="{DynamicResource HeroClassCheckbox}"/>
</Grid>

My .xaml.cs

public static class HeroClassCheckbox
{
    public static readonly DependencyProperty HeroClassProperty = DependencyProperty.RegisterAttached("HeroClass",
        typeof(string), typeof(HeroClassCheckbox), new FrameworkPropertyMetadata(null));

    public static string GetHeroClass(UIElement element)
    {
        if (element == null)
            throw new ArgumentNullException("element");
        return (string)element.GetValue(HeroClassProperty);
    }
    public static void SetHeroClass(UIElement element, string value)
    {
        if (element == null)
            throw new ArgumentNullException("element");
        element.SetValue(HeroClassProperty, value);
    }
}

Solution

  • You should use a converter as an approach to your goal. Here is an example..

        public class HelloLabelConverter : IValueConverter
        {
                public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
                {
                        char[] removeThis = "Hello ".ToCharArray();
                        return value.ToString().TrimStart(removeThis);
                }
    
                public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
                {
                        return string.Format("Hello {0}", value);
                }
        }
    
       <Window.Resources>
                <local:HelloLabelConverter x:Key="HelloLabelConverter" />
       </Window.Resources>
       <Grid>
           <Label Content="{Binding ElementName= lblPropertyToBind, Path=Text, Converter={StaticResource HelloLabelConverter}}"></Label>
       </Grid>