Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display dynamic culture formatted number in a WPF UserControl

I would like to dynamically set the culture format of the Number textblock with culture and number values passed through to MyUserControl. The MyCulture and Number values are passed to MyCustomControl and will be of the form "en-GB", "en-US" etc.

I did something similar in asp.NET MVC with an extension method but need help for how to piece this together in WPF.

Example MVC Extension Method

public static MvcHtmlString CulturedAmount(this decimal value, 
    string format, string locale)
{
    if (string.IsNullOrEmpty(locale))
        locale = HttpContext.Current.Request.UserLanguages[0];

    return MvcHtmlString.Create(value.ToString(format, 
        CultureInfo.CreateSpecificCulture(locale)));
}

Window

//MyMoney is a decimal, MyCulture is a string (e.g. "en-US")
<MyCustomControl Number="{Binding MyMoney}" Culture="{Binding MyCulture}" 
    Text="Some Text" />

MyCustomControl

<StackPanel>
    <TextBlock Text="{Binding Number, ElementName=BoxPanelElement, 
        StringFormat={}{0:C}}" /> //display this with specific culture
    <TextBlock Text="{Binding Text, ElementName=BoxPanelElement}" />
</StackPanel>
like image 277
David Avatar asked Aug 22 '11 19:08

David


2 Answers

If I understand your question correctly you want to bind the culture for a specific TextBlock.

You can't bind the properties of a Binding so binding ConverterCulture won't work.

There is a Language property on FrameworkElement which works fine to set like this

<TextBlock Language="en-US"
           Text="{Binding Number,
                          ElementName=BoxPanelElement,
                          StringFormat={}{0:C}}"/>

However, when trying to bind this property I get a weird exception
I'm probably going to ask a question on this exception myself

Binding for property 'Language' cannot use the target element's Language for conversion; if a culture is required, ConverterCulture must be explicitly specified on the Binding.

According to this answer by Thomas Levesque this should be possible though so maybe I did something wrong.. WPF xml:lang/Language binding

All I got working was using an attached behavior which in turn updated Language when MyCulture updated.

<TextBlock local:LanguageBehavior.Language="{Binding MyCulture}"
           Text="{Binding MyNumber,
                          ElementName=BoxPanelElement,
                          StringFormat={}{0:C}}"/>

LanguageBehavior

public class LanguageBehavior
{
    public static DependencyProperty LanguageProperty =
        DependencyProperty.RegisterAttached("Language",
                                            typeof(string),
                                            typeof(LanguageBehavior),
                                            new UIPropertyMetadata(LanguageBehavior.OnLanguageChanged));

    public static void SetLanguage(FrameworkElement target, string value)
    {
        target.SetValue(LanguageBehavior.LanguageProperty, value);
    }
    public static string GetLanguage(FrameworkElement target)
    {
        return (string)target.GetValue(LanguageBehavior.LanguageProperty);
    }
    private static void OnLanguageChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
    {
        FrameworkElement element = target as FrameworkElement;
        element.Language = XmlLanguage.GetLanguage(e.NewValue.ToString());
    }
}
like image 146
Fredrik Hedblad Avatar answered Sep 20 '22 14:09

Fredrik Hedblad


It seems like a converter is the answer. The interface includes a values for culture.

    Convert(object value, Type targetType, object parameter, CultureInfo culture) 

But I could not find syntax for passing culture. Sorry this is not a full and tested answer but I ran out of time.

URL on binding culture.
http://msdn.microsoft.com/en-us/library/system.windows.data.binding.converterculture.aspx

The syntax for passing a a parameter is:

    Converter={StaticResource colorConverter}, ConverterParameter=GREEN}" 

You may need to pass culture as a string using ConverterParameter.

I agree with Meleak that cannot bind the parameter to a converter. Gave him a +1. But I think you can fool it with a MultiBinding converter.

    <TextBlock Name="textBox2" DataContext="{StaticResource NameListData}">
        <TextBlock.Text>
            <MultiBinding Converter="{StaticResource myCutlureConverter}"
              ConverterParameter="FormatLastFirst">
                  <Binding Path="InputValue"/>
                  <Binding Path="CultureTxt"/>
            </MultiBinding>
         </TextBlock.Text>
    </TextBlock>
like image 39
paparazzo Avatar answered Sep 21 '22 14:09

paparazzo