I'm trying to use an MvxValueConverter to set the background color of a LinearLayout based on a boolean value. The converter looks like this:
public class BackgroundColorValueConverter : MvxValueConverter<bool, MvxColor>
{
private static readonly MvxColor TrueBGColor = new MvxColor(0xDB, 0xFF, 0xCE);
private static readonly MvxColor FalseBGColor = new MvxColor(0xD6, 0xF6, 0xFF);
protected override MvxColor Convert(bool value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value ? TrueBGColor : FalseBGColor;
}
}
In my AXML layout, I have the following code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
local:MvxBind="BackgroundColor MyBooleanValue, Converter=BackgroundColor">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="18dp"
local:MvxBind="Text MyText" />
</LinearLayout>
I'm getting the following error:
Failed to create target binding for binding BackgroundColor for MyBooleanValue
The full error trace is as follows:
MvxBind:Error: 8.58 Problem seen during binding execution for binding BackgroundColor for MyBooleanValue - problem InvalidCastException: Cannot cast from source type to destination type.
03-05 14:18:46.434 I/mono-stdout(16474): MvxBind:Error: 8.58 Problem seen during binding execution for binding BackgroundColor for MyBooleanValue - problem InvalidCastException: Cannot cast from source type to destination type.
03-05 14:18:46.434 I/mono-stdout(16474): at Cirrious.MvvmCross.Plugins.Color.Droid.BindingTargets.MvxViewBackgroundColorBinding.SetValueImpl (System.Object target, System.Object value) [0x00000] in <filename unknown>:0
at Cirrious.MvvmCross.Plugins.Color.Droid.BindingTargets.MvxViewBackgroundColorBinding.SetValueImpl (System.Object target, System.Object value) [0x00000] in <filename unknown>:0
at Cirrious.MvvmCross.Binding.Bindings.Target.MvxConvertingTargetBinding.SetValue (System.Object value) [0x00000] in <filename unknown>:0
03-05 14:18:46.434 I/mono-stdout(16474): at Cirrious.MvvmCross.Binding.Bindings.Target.MvxConvertingTargetBinding.SetValue (System.Object value) [0x00000] in <filename unknown>:0
at Cirrious.MvvmCross.Binding.Bindings.MvxFullBinding.UpdateTargetFromSource (System.Object value) [0x00000] in <filename unknown>:0
So, I'm honestly not sure where to go from here. Is what I'm attempting possible? Am I using the right MvvmCross converter? Any pointers would be much appreciated.
Update:
Changing the converter to:
public class BackgroundColorValueConverter : MvxColorValueConverter
{
private static readonly MvxColor TrueBGColor = new MvxColor(0xDB, 0xFF, 0xCE);
private static readonly MvxColor FalseBGColor = new MvxColor(0xD6, 0xF6, 0xFF);
protected override MvxColor Convert(object value, object parameter, System.Globalization.CultureInfo culture)
{
return (bool)value ? TrueBGColor : FalseBGColor;
}
}
... resolved my problem. I also had TextColor MyBooleanValue, Converter=TextColor
on my LinearLayout
, which functioned similarly to BackgroundColorValueConverter
, and I was getting the same error about failing to create target bindings.
Once I changed my AXML to read:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
local:MvxBind="BackgroundColor MyBooleanValue, Converter=BackgroundColor">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="18dp"
local:MvxBind="Text MyText; TextColor MyBooleanValue, Converter=TextColor" />
</LinearLayout>
... everything worked as intended. For anyone who happens to stumble across this in the future: don't try to bind TextColor
on a LinearLayout
, because it doesn't work like that!
There's a working sample of BackgroundColor
binding in https://github.com/MvvmCross/MvvmCross-Tutorials/blob/master/ValueConversion/ValueConversion.UI.Droid/Resources/Layout/View_Colors.axml
This uses the BackgroundColor binding from https://github.com/MvvmCross/MvvmCross/blob/v3.1/Plugins/Cirrious/Color/Cirrious.MvvmCross.Plugins.Color.Droid/BindingTargets/MvxViewBackgroundColorBinding.cs
Does this sample work for you?
If yes, can you spot the difference between that sample and the one you are using? Is it some problem with the Color plugin? (Is that loaded in your UI project?) Is it an issue with LinearLayout versus TextView? Is there any more error trace you can provide? The one line of trace you have provided is created on https://github.com/MvvmCross/MvvmCross/blob/1ec7bc5f0307595c7ae11f56727dd0e9d2a2262f/Cirrious/Cirrious.MvvmCross.Binding/Bindings/MvxFullBinding.cs#L139 - but there's normally other trace before that line.
If no, then that's worrying as it means it's a general bug...
Update: (after more info provided)
I think the problem is in your ValueConverter - to work with Android, your ValueConverter has to end up with a Native type - not the platform-independent MvxColor
. The error you are seeing is an invalid cast exception - because the binding is trying to cast your MvxColor
to an Android.Graphics.Color
in https://github.com/MvvmCross/MvvmCross/blob/v3.1/Plugins/Cirrious/Color/Cirrious.MvvmCross.Plugins.Color.Droid/BindingTargets/MvxViewBackgroundColorBinding.cs#L25
To convert to Native, you can use the MvxColorValueConverter
base class - see https://github.com/MvvmCross/MvvmCross/blob/v3.1/Plugins/Cirrious/Color/Cirrious.MvvmCross.Plugins.Color/MvxColorValueConverter.cs
One example of this is https://github.com/MvvmCross/MvvmCross-Tutorials/blob/master/ValueConversion/ValueConversion.Core/Converters/Converters.cs#L35
public class ContrastColorConverter : MvxColorValueConverter
{
protected override MvxColor Convert(object value, object parameter, CultureInfo culture)
{
var input = (MvxColor) value;
var brightnessToUse = SimpleContrast(input.R, input.G, input.B);
return new MvxColor(brightnessToUse, brightnessToUse, brightnessToUse);
}
private static int SimpleContrast(params int[] value)
{
// this is only a very simple contrast method
// for more advanced methods you need to look at HSV-type approaches
int max = 0;
foreach (var v in value)
{
if (v > max)
max = v;
}
return 255 - max;
}
}
There are some docs on Color Converters in https://github.com/MvvmCross/MvvmCross/wiki/Value-Converters#wiki-the-mvx-color-valueconverters
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With