Converter does not work after calling OnPropertyChanged - xaml

I have been trying to make this work for a while with no success.
I have a converter to pretty print dates on the page. Convert function is as follows;
class DateConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
Nullable<int> _date = value as Nullable<int>;
if (!_date.HasValue)
return DependencyProperty.UnsetValue;
if (!String.IsNullOrEmpty(parameter as String))
{
if (parameter.Equals("EDITED"))
return "edited " + UtilityFunctions.formatUnixTime(_date.Value);
}
return UtilityFunctions.formatUnixTime(_date.Value);
}
}
In XAML part I am using this converter by passing a property of a property to it.
<TextBlock Text="{Binding Wiki.EditDate, Converter={StaticResource DateConverter}, ConverterParameter=EDITED}" />
My ModelView extends BindableBase and whenever I update Wiki property, I call SetProperty which in return calls OnPropertyChanged for Wiki property.
If I try to show the date without a converter, it works fine.
<TextBlock Text="{Binding Wiki.EditDate}" />
I am using this converter in other parts of my projects so I believe it is not the cause of the problem.
What might be the cause of this problem?
Thanks for any helps...

As it turned out in discussion and debugging - the problem was that the value passed to converter was wrong - "2014-06-03 00:56:21".
Such value can't be coverted to int, and because you are using as:
Nullable<int> _date = value as Nullable<int>;
there won't be exception thrown. Instead of exception you have null (as doesn't throw InvalidCastException).
If you would use cast:
Nullable<int> _date = (Nullable<int>)value;
then you would have an exception. Some more information you will surely find on SO - for example this answer.

Related

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.
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!
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} />
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

what is equivalent of listview adapter of android in windows phone 8.1(Xaml)

I know that we can directly bind properties in Xaml.
But My requirement is bit different. I want full control on binding data.
So I am looking for adapter type approach. I want to display some elements based on number of lines in textblock of that item. Here i cant use value converter because at that time my UI won't be ready and I cant find number of lines of each textblocks.
I will explain with example, let's suppose I want to change time format from hh:mm:ss to hh:mm during binding.
First, I will create public class that implements IValueConverter.
for example :-
public class RemoveSecondsInTime : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
string date = value as string;
date = date.Substring(0, date.Length - 3);
return date;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
Second, To use this converter class, we need to add this converter class in page resources.
for example :-
<Page.Resources>
<local:RemoveSecondsInTime x:Key="ChangeTimeFormat" />
</Page.Resources>
Third, We will create create our ListView as following :-
<ListView>
<ListView.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding TimeWithSeconds, Converter {StaticResource ChangeTimeFormat}}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
So, TimeWithSeconds will pass as "value" parameter in Convert function, Convert function will return formatted string to be displayed in textBox.
References :-
1) https://channel9.msdn.com/Series/Windows-Phone-8-1-Development-for-Absolute-Beginners/Part-25-Advanced-Binding-with-Value-Converters
2) https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.data.ivalueconverter

StringFormat in XAML

I am trying to format my string to have commas every 3 places, and a decimal if it is not a whole number. I have checked roughly 20 examples, and this is the closest I have come:
<TextBlock x:Name="countTextBlock" Text="{Binding Count, StringFormat={0:n}}" />
But I get a The property 'StringFormat' was not found in type 'Binding'. error.
Any ideas what is wrong here? Windows Phone 8.1 appears to differ from WPF, because all of the WPF resources say that this is how it is done.
(The string is updated constantly, so I need the code to be in the XAML. I also need it to remain binded. Unless of course I cannot have my cake and eat it too.)
It seems that, similar to Binding in WinRT, Binding in Windows Phone Universal Apps doesn't have StringFormat property. One possible way to work around this limitation is using Converter as explained in this blog post,
To summarize the post, you can create an IValueConverter implmentation that accept string format as parameter :
public sealed class StringFormatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value == null)
return null;
if (parameter == null)
return value;
return string.Format((string)parameter, value);
}
public object ConvertBack(object value, Type targetType, object parameter,
string language)
{
throw new NotImplementedException();
}
}
Create a resource of above converter in your XAML, then you can use it like this for example :
<TextBlock x:Name="countTextBlock"
Text="{Binding Count,
Converter={StaticResource StringFormatConverter},
ConverterParameter='{}{0:n}'}" />

Reference to current class xaml Windows Phone

I got the following code:
namespace SomeApp
{
public partial class MyClass : PhoneApplicationPage, IValueConverter
{
SOME METHODS...
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return true;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return true;
}
}
}
I would like to bind this class to a ValueConverter of a RadioButton. Is there any way to reference to the current class I'm working with? For example:
<phone:PhoneApplicationPage
x:Class="SomeApp.MyClass"
xmlns:local="clr-namespace:SomeApp">
<phone:PhoneApplicationPage.Resources>
<local:MyClass x:Key="myClass"/>
</phone:PhoneApplicationPage.Resources>
<RadioButton IsChecked="{Binding Converter={StaticResource myClass}}"/>
Thanks in advance =)
First using your page as a converter don't seem like a good idea, it's better practice to separate the converter fonctionality in a separate class. Particularly it would be a very bad idea to create a StaticResources of a converter created that way as it will use a lot of unessessary memory to create the whole page.
The only thing a converter can be binded in xaml is a StaticResource so you will not be able to do it in xaml but if you really want to do it you could do it by creating the binding from code behind (for example in the constructor of the page):
Binding binding=new Binding();
binding.Converter = this;
myRadioButton.SetBinding(CheckBox.IsCheckedProperty, binding);

StringFormat does not work in Silverlight Control

I have a piece of code for a Text Box in a XAML File. The text box takes as input Numeric Value.Below is the piece of code:-
<TextBox Text="{Binding Path=Revenue, StringFormat=c0, Mode=TwoWay, Converter={StaticResource NullableConverter}, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Grid.Column="3" Grid.Row="2"/>
However if I input 5 and tab out the input does not become 5 $. However, on saving the data in the page and loading the page the formatting is intact. Any thoughts on this ??
please remove the converter and try it, you should get it. should be something wrong with converter.
this is what I tried for Nullable Converter it worked.
public class NullableConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return 0;
else
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
If you are using SL5 I think this is a bug, the StringFormat is not triggered when the binding is updated. For more details here is the MS connect issue. You can check the workaround it might help you solving the problem.