1
votes

I have a WPF Expander in my project. I have applied styles to the expander to change the header colors and whatnot. After doing so, my data is still bound to the Header's content area, but it just binds the raw data and not the formatting I have specified. See the examples below.

<Style x:Key="ValkyrieStyleExpander" TargetType="{x:Type Expander}">
   <!-- Ommiting property setters for brevity -->
   <Setter Property="HeaderTemplate">
       <Setter.Value>
            <DataTemplate>
                <TextBlock Text="{Binding}" FontWeight="Bold" 
                           Foreground="White" VerticalAlignment="Center" />
            </DataTemplate>
        </Setter.Value>
   </Setter>
</Style>

And here is the actual declaration with the appropriate binding syntax

<Expander Style="{StaticResource ValkyrieStyleExpander}" 
           Margin="10,10,0,0" 
           Width="670" 
           Header="{Binding PolicyNumber, StringFormat=Policy {0}}">
</Expander>

We I run the app, the header should display "Policy 123456", and before I restyled the expander it did so. But now when I run the app, the header just shows "123456". I am still kind of a babe-in-the-woods when it comes to databinding, so I am not sure really what I need to do to get the new style to show the correct data. Hopefully the answer isn't to add it to the ValkyrieStyleExpender's Header Template style, as that would defeat the purpose of having a style (Not all expanders in the project are for displaying a particular policy)

2
Can you please give an example where it works without a style (because normally StringFormat never should work in a binding for the Expander.Header property)? StringFormat works only for properties that have type string.user128300
PolicyNumber is of type string?Rohit Vats
@Rohit, yes the policy number is a string property on the view model.Peter Lange
@fmunkert, just removed the style declaration from the expander and it worked for mePeter Lange
Not sure what you edited, @Andy G, but congratulations on a wonderful choice of icon, lol.Peter Lange

2 Answers

1
votes

StringFormat usually does not work when using it within the Expander.Header property since the property is not of type string.

You will need to write your own class derived from IFormatter that implements the formatted string you'd actually define in the property. I've researched quite a bit and found no better solution for this issue.

The class may look as follows:

public class SomeClass: IFormattable
{
    public string ToString(string format, IFormatProvider formatProvider)
    {
        if(format == "n")
        {
            return "This is the formatted string";
        }
        else
        {
            return "this is the non-formatted string";
        }
    }
}

And you would use it in your style this way:

Setter Property="HeaderStringFormat" Value="n" />
1
votes

If the string format is not working for you, you can easily implement a converter, such as...

#region PolicyConverter (ValueConverter)
public class PolicyConverter : MarkupExtension, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
        {
            return "Policy " + value.ToString();
        }
        return null;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}
#endregion

...and then declare it in your Xaml...

<Window.Resources>
    <pc:PolicyConverter x:Key="PolicyConverter"/>
</Window.Resources>

...and finally reference it in your template. I did not use (or modify) your ValkyrieStyleExpander code. But to verify the correctness of this approach, I used the following declaration as a functional prototype...

    <Expander Name="Expander1">
        <Expander.HeaderTemplate>
            <DataTemplate>
                <TextBlock 
                    Text="{Binding ElementName=Expander1, 
                    Path=DataContext.PolicyNumber, 
                    Converter={StaticResource PolicyConverter}}"/>
            </DataTemplate>
        </Expander.HeaderTemplate>
    </Expander>

...and it worked as expected (.net 4.5). If you needed to evacuate the in-lined templating to a global declaration in your Xaml, this would also make a great starting point.