I am currently re-writing my phone app for my bank budgeting application (Quid). One page is the list of Transactions. Transfers (transferring between "Envelopes") don't have a balance. Therefore I want a different <Label ...\> displayed for the Amount column of all Transfer transactions:
Obviously this needs to bind something to IsVisible.
My viewmodel already has an IsTransfer property on it:
class TransactionViewModel
{
public bool IsTransfer { get; set; }
}
With this, I can bind the "N/A" label as such:
<Label
IsVisible="{Binding IsTransfer}"
Text="N/A"
/>
However, now I need the Amount label to be hidden when this is displayed. It therefore needs to bind to the inverse of IsTransfer. Unfortunately we can't bind to !IsTransfer.
Hack #1: Add another property to the viewmodel
Since we can't bind to !IsTransfer, here's a quick hack: Add a IsNotTransaction property to my view model:
class TransactionViewModel
{
public bool IsTransfer { get; set; }
public bool IsNotTransaction { get { return !IsTransfer; } }
}
Now map my amount Label to it:
<Label
IsVisible="{Binding IsNotTransfer}"
Text="{Binding Amount, StringFormat='{0:c}'}"
/>
Although this works, it's sloppy coding. The preferred is...
Option #2: Use an IValueConverter.
There's a more proper answer to this. Converters are rather easy to write. Create a class that inherits from IValueConvert and add it to your project. For mine, I needed to invert a bool to essentially get !IsTransfer. So I created this class:
namespace QuidXam.Infrastructure.Converters
{
public class InverseBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return !((bool)value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
}
}
Next, this needs to be added to a ResourceDictionary. This can be done in each page where you need it, but I prefer to place it in the App.xaml file. In there, add the namespace, and this entry into the ResourceDictionary:
xmlns:converter="clr-namespace:QuidXam.Infrastructure.Converters"
...
<Application.Resources>
<ResourceDictionary>
<converter:InverseBoolConverter x:Key="inverseBoolConverter" />
</ResourceDictionary>
</Application.Resources>
Now I no longer need my IsNotTransfer property, and my Amount Label can be implemented as follows:
<Label
IsVisible="{Binding IsTransfer, Converter={StaticResource inverseBoolConverter}}"
Text="{Binding Amount, StringFormat='{0:c}'}"
/>
Of all the IValueConverter's you would create, this one is the most useful. As I mentioned, just about every Xamarin app you create will most likely need this.