RareNCool
RareNCool

Reputation: 436

Specify signature when using x:Bind

UWP allows you to bind to a static method. I'm trying to get a time string by using

<TextBlock Text={x:Bind MyDateTime.ToString(MyPatternString)} />

where MyPatternString is "h:mm tt".

The problem is that DateTime's ToString() method has several different signatures. The first one receives an IFormatProvider. Because of this, I get a build error:

Function parameter 'provider' is invalid or missmatched

Is there any way to tell it that I wish to use the signature which accepts a string? I'd have thought it would automatically know this.

Upvotes: 1

Views: 661

Answers (3)

Joel Janssen
Joel Janssen

Reputation: 41

Found your question after searching for the answer myself; didn't find much help posted anywhere but did figure it out after some trial and error.

Function parameter 'provider' is invalid or mismatched

The reason for this that in XAML, a specific overload is being called which is DateTimeProperty.ToString(string, IFormatProvider).

In my case, any value I display is within a User Control so for each I added a CultureInfo dependency property and bound it to common source on my view model.

If C#, add:

using System.Globalization;

Then

public static readonly DependencyProperty CultureInfoProperty = DependencyProperty.Register(
        "CultureInfo", typeof(CultureInfo), typeof(XyzReadoutView), new PropertyMetadata(default(CultureInfo)));

    public CultureInfo CultureInfo
    {
        get { return (CultureInfo) GetValue(CultureInfoProperty); }
        set { SetValue(CultureInfoProperty, value); }
    }

This creates a local instance required for x:Bind, compile errors occur if using a static property.

And XAML:

<TextBlock Text={x:Bind MyDateTime.ToString('h:mm tt', CultureInfo)} />

Notice the format is surrounded with ' and not ".

Also, this will only update once as the mode for x:Bind has a default of Mode=OneTime; if you want changes on the DateTime or CultureInfo to propagate, the mode must be changed to Mode=OneWay.

<TextBlock Text={x:Bind MyDateTime.ToString('h:mm tt', CultureInfo), Mode=OneWay} />

If the format is user changeable, I would create a dependency property for it as well for updates and easy control binding back to a view model but that's just my personal preference.

public static readonly DependencyProperty DateTimeFormatProperty = DependencyProperty.Register(
        "DateTimeFormat", typeof(string), typeof(XyzReadoutView), new PropertyMetadata(default(string)));

    public string DateTimeFormat
    {
        get { return (string) GetValue(DateTimeFormatProperty); }
        set { SetValue(DateTimeFormatProperty, value); }
    }

And XAML:

<TextBlock Text={x:Bind MyDateTime.ToString(DateTimeFormat, CultureInfo), Mode=OneWay} />

Upvotes: 0

Pedro Lamas
Pedro Lamas

Reputation: 7233

You can just add a method to your ViewModel and use that instead!

That way your binding expression can be changed to this:

<TextBlock Text={x:Bind FormatDateToString(MyDateTime)} />

Be advised that this works with the Windows 10 Anniversary Update only! More info on this matter here!

Upvotes: 2

Ken Tucker
Ken Tucker

Reputation: 4156

You need to use an IValueConverter to format the text for display. Create a class which inherits from IValueConverter.

public class DateFormatter : IValueConverter
{
    // This converts the DateTime object to the string to display.
    public object Convert(object value, Type targetType, 
        object parameter, string language)
    {
        // Retrieve the format string and use it to format the value.
        string formatString = parameter as string;
        if (!string.IsNullOrEmpty(formatString))
        {
            return string.Format(
                new CultureInfo(language), formatString, value);
        }
        // If the format string is null or empty, simply call ToString()
        // on the value.
        return value.ToString();
    }

    // No need to implement converting back on a one-way binding 
    public object ConvertBack(object value, Type targetType, 
        object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

Register it as resource on the Page and then you can specify the converter in the binding

<TextBlock Text={x:Bind MyDateTime, Converter={StaticResource DateFormatConverter}}, ConverterParameter="mm/dd/yyyy"}"/>

https://learn.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Data.IValueConverter

Upvotes: -1

Related Questions