3

I am trying to bind the text color of a TextView in Android. Here is my (truncated) xaml:

<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:MvxBind=" TextColor CategoryTextColor(Category)"/>

where CategoryTextColorValueConverter is as follows:

public class CategoryTextColorConverter : MvxValueConverter<ShowCategory, Color>
{
    protected override Color Convert (ShowCategory value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == ShowCategory.AllShows)
        {
            return Color.Blue;
        }
        return Color.Red;
    }
}

The converter is getting called and returns a colour as expected, but the text colour never changes on the TextView. I have a similar binding for the background colour that works fine. I've seen here In MvvmCross how do I do custom bind properties that maybe I need to create a custom binding, but I cannot find MvxBaseAndroidTargetBinding. Perhaps I need to install a separate package from nuget?

Community
  • 1
  • 1
David Conlisk
  • 3,387
  • 4
  • 33
  • 39

4 Answers4

8

The only thing you have to do, is installing the MvvMCross Color Plugin, because TextColor comes with it. It is not included in Core. Your posted solution works.

See: https://github.com/MvvmCross/MvvmCross/wiki/MvvmCross-plugins#color

Tip: You don't have to write platform specific ValueConvertes, if you use MvxColorValueConverter<ShowCategory>, you can share it across different platforms.

public class CategoryTextColorConverter : MvxColorValueConverter<ShowCategory>
{
    protected override MvxColor Convert(ShowCategory value, object parameter, CultureInfo culture)
    {
        if (value == ShowCategory.AllShows)
        {
            return MvxColors.Blue;
        }
        return MvxColors.Red;
    }
}
Sven-Michael Stübe
  • 14,560
  • 4
  • 52
  • 103
  • 1
    I am using this one, the text itself not visible now. I kept a break point in convert method, it is not coming over there. – GvSharma Oct 24 '17 at 06:17
2

The MVVMCross bindings work by binding to an object's properties and while android:textColor works fine in Android XML it is a shortcut to the object's underlying method, SetTextColor which you can't bind to directly. What you can do is create a class that extends the TextView and have a bindable TextColor property and then use that in your Android XML and bind to that. For example:

public class ExtendedTextView : TextView
{
    public ExtendedTextView(Context context): base (context) { }
    public ExtendedTextView(Context context, IAttributeSet attrs) : base (context, attrs) { }
    public ExtendedTextView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr) { }
    public ExtendedTextView(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base (context, attrs, defStyleAttr, defStyleRes) { }
    protected ExtendedTextView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }

    public Color BindableTextColor // property to bind to in XML
    {
        get { return new Color(CurrentTextColor); }
        set { SetTextColor(value);}
    }
}
Kevin Ford
  • 286
  • 1
  • 3
  • This looks like it should work, but the colour never changes despite the setter for BindableTextColor being called as expected with the new colour value. – David Conlisk Mar 21 '16 at 16:04
1

Thanks for the input all - ideally I would have used @sven-michael's cross-platform solution but I ended up implementing a custom binding in Android.

My code is below. Note that MvxBaseAndroidTargetBinding is now called MvxAndroidTargetBinding.

public class TextColorBinding : MvxAndroidTargetBinding {

    private readonly TextView _textView;

    public TextColorBinding(TextView textView) : base(textView)
    {

        _textView = textView;
    }

    public static void Register(IMvxTargetBindingFactoryRegistry registry) {
        registry.RegisterFactory(new MvxCustomBindingFactory<TextView>("TextColor", (textView) => new TextColorBinding(textView)));
    }

    #region implemented abstract members of MvxTargetBinding

    public override Type TargetType
    {
        get { return typeof(Color); }
    }

    #endregion

    #region implemented abstract members of MvxConvertingTargetBinding

    protected override void SetValueImpl (object target, object value)
    {
        var color = (Color)value;

        if (color != null) {

            var textView = (TextView)target;

            try {
                textView.SetTextColor (color);
            } catch (Exception ex) {
                MvxTrace.Error (ex.ToLongString ());
                throw;
            }

        } else {
            MvxBindingTrace.Trace (MvxTraceLevel.Warning, "Value was not a valid Color");
        }
    }
    #endregion
} 

Don't forget to register the binding in your Setup.cs as follows too:

protected override void FillTargetFactories(MvvmCross.Binding.Bindings.Target.Construction.IMvxTargetBindingFactoryRegistry registry)
    {
        TextColorBinding.Register (registry);
        base.FillTargetFactories(registry);
    }
David Conlisk
  • 3,387
  • 4
  • 33
  • 39
  • 2
    This is "exactly" what the mvvmcross color plugin does ^^ https://github.com/MvvmCross/MvvmCross-Plugins/blob/master/Color/MvvmCross.Plugins.Color.Droid/BindingTargets/MvxDefaultColorBindingSet.cs – Sven-Michael Stübe Mar 22 '16 at 12:37
  • Although this solution does work, I've removed this code from my project and installed the MvvmCross Color plugin which also works perfectly. Thanks @Sven-MichaelStübe - always a pleasure removing unnecessary code from a project :) – David Conlisk Mar 23 '16 at 13:53
  • 1
    Yes it was a good practice to understand how MvvMCross binds. You are now at least able to wirte custom views with bindable properties :) #achivementunlocked – Sven-Michael Stübe Mar 23 '16 at 13:56
0

For this purpose, color adjustment and other uses can use the following code sample:

Android.Graphics.Color color = new Android.Graphics.Color(element.CurrentTextColor);
Hadi Salehy
  • 260
  • 2
  • 6