Reputation: 436
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
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
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
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