MisevmCross自定义绑定未通过RaisePropertyChanged通知

时间:2017-04-14 19:34:54

标签: c# xamarin data-binding xamarin.android mvvmcross

我正在尝试在MvxImageView(在Android CardView中)实现可触发动画,以便在卡片的ViewModel上更改属性时将颜色(绿色或红色)覆盖到图像上。我使用Stuart Lodge的示例here创建了自定义类DynamicImageView。

public class DynamicImageView : MvxImageView
{
    public DynamicImageView(Context context) : base(context)
    {
    }

    public DynamicImageView(Context context, IAttributeSet attrs) : base(context, attrs)
    {
    }

    public DynamicImageView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
    {
    }

    protected DynamicImageView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
    {
    }

    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        Drawable d = this.Drawable;

        if (d != null)
        {
            // ceil not round - avoid thin vertical gaps along the left/right edges
            int width = MeasureSpec.GetSize(widthMeasureSpec);
            int height = (int)Math.Ceiling(width * (float)d.IntrinsicHeight / d.IntrinsicWidth);
            this.SetMeasuredDimension(width, height);
        }
        else
        {
            base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    private ObjectAnimator colorFilterAnimation;

    private string _animatingColor;
    public string AnimatingColor
    {
        set
        {
            System.Diagnostics.Debug.WriteLine("Animation triggered");
            if (value != _animatingColor)
            {
                _animatingColor = value;
                colorFilterAnimation = ObjectAnimator.OfObject((ImageView)this, "colorFilter", new ArgbEvaluator(), 0, 0);
                switch (value)
                {
                    case "red":
                        colorFilterAnimation.SetObjectValues(0, new Color(100, 0, 0, 80).ToArgb());
                        System.Diagnostics.Debug.WriteLine("Starting Red Animation");
                        break;
                    case "green":
                        colorFilterAnimation.SetObjectValues(0, (int)Color.Green);
                        System.Diagnostics.Debug.WriteLine("Starting Green Animation");
                        break;
                }
                colorFilterAnimation.SetDuration(1000);
                colorFilterAnimation.Start();
            }
        }
    }
}

在此控件的ViewModel中,我也按照标准MvvmCross表示法定义了匹配属性:

private string _animatingColor;
    public string AnimatingColor {
        get
        {
            return _animatingColor;
        }
        set
        {
            _animatingColor = value;
            Debug.WriteLine("AnimatingColor set to " + value);
            RaisePropertyChanged(() => AnimatingColor);
        }
    }

单击该卡时更改了此属性,当我单击时,我会在属性set中看到Debug打印,但它似乎没有触发AnimatingColor的set在控制之内。 axml中的控件正常引用:

<DynamicImageView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:scaleType="centerCrop"
  local:MvxBind="ImageUrl 'http:'+Profile.Headshot.Url; AnimatingColor .AnimatingColor" />

并且值得,imageUrl确实正确绑定,并在ViewModel中更改Url时按预期更新。此外,Debug.PrintLine("Animation triggered")会在创建卡时打印,但从不在ViewModel上更改属性时打印。

2 个答案:

答案 0 :(得分:0)

正如评论所示,我认为您需要为DynamicImageView控件创建自定义绑定。这样的事情应该这样做:

public class DynamicImageViewAnimatingColorBinding : MvxTargetBinding
{
    public DynamicImageViewAnimatingColorBinding(DynamicImageView target) : base(target)
    {
    }

    protected DynamicImageView View => Target as DynamicImageView;

    public override MvxBindingMode DefaultMode => MvxBindingMode.OneWay;

    public override Type TargetType => typeof(string);

    public override void SetValue(object value)
    {
        var view = View;
        if (view == null)
            return;

        view.AnimatingColor = (string) value;
    }
}

然后在您的安装程序类中,您需要注册它以便MvvmCross可以使用它:

protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
    {
        registry.RegisterCustomBindingFactory<DynamicImageView>(
            nameof(DynamicImageView.AnimatingColor),
            image => new DynamicImageViewAnimatingColorBinding (image));

        base.FillTargetFactories(registry);
    }

我没有测试过这段代码,它基于我在iOS上使用的一些非常相似的代码,但它在Android上运行良好。希望这会有所帮助。

答案 1 :(得分:0)

James Mundy的问题使我意识到底层问题是我没有在列表中使用ObservableCollection,因此底层ViewModel的更改没有反映在UI中。