Mvvmcross绑定 [英] Mvvmcross Binding

查看:65
本文介绍了Mvvmcross绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将小部件绑定到viewmodel属性,但出现异常

I tried to bind a widget to a viewmodel property but I'm getting an exception

MvxBind:Warning: 14.76 Failed to create target binding for binding Signature for Order.ClientSignature
[0:] MvxBind:Warning: 14.76 Failed to create target binding for binding Signature for Order.ClientSignature
04-26 21:02:15.380 I/mono-stdout(32490): MvxBind:Warning: 14.76 Failed to create target binding for binding Signature for Order.ClientSignature

该小部件由 Al taiar

axml是

<SignatureWidget
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:id="@+id/signatureWidget1"
        android:layout_marginRight="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginBottom="5dp"
        local:MvxBind="Signature Order.ClientSignature" />

该视图的代码为

using Android.Content;
using Android.Graphics;
using Android.Util;
using Android.Views;
using Core.Models;
using System;

public class SignatureWidget
    : View
{
    #region Implementation

    private Bitmap _bitmap;
    private Canvas _canvas;
    private readonly Path _path;
    private readonly Paint _bitmapPaint;
    private readonly Paint _paint;

    private float _mX, _mY;
    private const float TouchTolerance = 4;

    #endregion

    public Signature Signature;

    public event EventHandler SignatureChanged;

    public SignatureWidget(Context context, IAttributeSet attrs)
        : base(context, attrs)
    {
        Signature = new Signature();

        _path = new Path();
        _bitmapPaint = new Paint(PaintFlags.Dither);
        _paint = new Paint
        {
            AntiAlias = true,
            Dither = true,
            Color = Color.Argb(250, 00, 0, 0)
        };
        _paint.SetStyle(Paint.Style.Stroke);
        _paint.StrokeJoin = Paint.Join.Round;
        _paint.StrokeCap = Paint.Cap.Round;
        _paint.StrokeWidth = 5;
    }

    protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
    {
        base.OnSizeChanged(w, h, oldw, oldh);
        _bitmap = Bitmap.CreateBitmap(w, (h > 0 ? h : ((View)this.Parent).Height), Bitmap.Config.Argb8888);
        _canvas = new Canvas(_bitmap);
    }

    protected override void OnDraw(Canvas canvas)
    {
        canvas.DrawColor(Color.White);
        canvas.DrawBitmap(_bitmap, 0, 0, _bitmapPaint);
        canvas.DrawPath(_path, _paint);
    }

    private void TouchStart(float x, float y)
    {
        _path.Reset();
        _path.MoveTo(x, y);
        _mX = x;
        _mY = y;
        Signature.AddPoint(SignatureState.Start, (int)x, (int)y);
    }

    private void TouchMove(float x, float y)
    {
        float dx = Math.Abs(x - _mX);
        float dy = Math.Abs(y - _mY);

        if (dx >= TouchTolerance || dy >= TouchTolerance)
        {
            _path.QuadTo(_mX, _mY, (x + _mX) / 2, (y + _mY) / 2);
            Signature.AddPoint(SignatureState.Move, (int)x, (int)y);
            _mX = x;
            _mY = y;
        }
    }

    private void TouchUp()
    {
        if (!_path.IsEmpty)
        {
            _path.LineTo(_mX, _mY);
            _canvas.DrawPath(_path, _paint);
        }
        else
        {
            _canvas.DrawPoint(_mX, _mY, _paint);
        }
        Signature.AddPoint(SignatureState.End, (int)_mX, (int)_mY);

        _path.Reset();
    }

    public override bool OnTouchEvent(MotionEvent e)
    {
        var x = e.GetX();
        var y = e.GetY();

        switch (e.Action)
        {
            case MotionEventActions.Down:
                TouchStart(x, y);
                Invalidate();
                break;
            case MotionEventActions.Move:
                TouchMove(x, y);
                Invalidate();
                break;
            case MotionEventActions.Up:
                TouchUp();
                Invalidate();
                break;
        }

        RaiseSignatureChangedEvent();

        return true;
    }

    public void ClearCanvas()
    {
        _canvas.DrawColor(Color.White);
        Invalidate();
    }

    public Bitmap CanvasBitmap()
    {
        return _bitmap;
    }

    public void Clear()
    {
        ClearCanvas();
        Signature.Clear();

        RaiseSignatureChangedEvent();
    }

    private void RaiseSignatureChangedEvent()
    {
        var handler = SignatureChanged;
        if (handler != null)
            handler(this, EventArgs.Empty);
    }
}

该模型的代码为

public class Signature
{
    private List<Point> _currentPath;
    private readonly List<List<Point>> _paths;

    public event EventHandler PointAdded;

    public Signature()
    {
        _currentPath = new List<Point>();
        _paths = new List<List<Point>>();
    }

    public IReadOnlyList<IReadOnlyList<Point>> Paths
    {
        get { return _paths; }
    }

    public Point LastPoint()
    {
        if (_currentPath != null && _currentPath.Count > 0)
        {
            return _currentPath.Last();
        }

        return new Point(0, 0);
    }

    public void Clear()
    {
        _paths.Clear();
        _currentPath.Clear();
    }

    public void AddPoint(SignatureState state, int x, int y)
    {
        if (state == SignatureState.Start)
        {
            _currentPath = new List<Point>();
        }
        if (x != 0 && y != 0)
        {
            _currentPath.Add(new Point(x, y));
        }
        if (state == SignatureState.End)
        {
            if (_currentPath != null)
            {
                _paths.Add(_currentPath);
            }
        }

        RaisePointAddedEvent();
    }

    public int Length
    {
        get { return _paths.Count; }
    }

    protected void RaisePointAddedEvent()
    {
        if (PointAdded != null)
            PointAdded(this, EventArgs.Empty);
    }
}

此小部件需要双向绑定.有人愿意帮助吗?

I will need two-way binding for this widget. Anyone care to help???

我还需要添加清除"文本作为视图上的覆盖.单击此文本将触发清除小部件的命令.知道如何执行此操作吗?

I will also need to add a "Clear" text as an overlay on the view. Clicking this text will trigger a command to clear the widget. Any clue how to do this?

P.S: 我遵循了内容丰富的帖子,但我仍然无法使它正常工作.我添加了以下内容.

P.S: I've followed the informative post and I still cannot get it to work. I've added the following.

public class SignatureWidgetSignatureTargetBinding
    : MvxPropertyInfoTargetBinding<SignatureWidget>
{
    public SignatureWidgetSignatureTargetBinding(object target, PropertyInfo targetPropertyInfo)
        : base(target, targetPropertyInfo)
    {
        View.SignatureChanged += OnSignatureChanged;
    }

    public override MvxBindingMode DefaultMode
    {
        get { return MvxBindingMode.TwoWay; }
    }

    private void OnSignatureChanged(object sender, EventArgs eventArgs)
    {
        FireValueChanged(View.Signature);
    }

    protected override void Dispose(bool isDisposing)
    {
        base.Dispose(isDisposing);
        if (isDisposing)
        {
            View.SignatureChanged -= OnSignatureChanged;
        }
    }
}

并使用

registry.RegisterFactory(new MvxSimplePropertyInfoTargetBindingFactory(typeof(SignatureWidgetSignatureTargetBinding), typeof(SignatureWidget), "Signature"));

推荐答案

如果使用以下格式建模,MvvmCross将自动绑定视图属性:

MvvmCross will automatically bind a View property if you model it using the format:

  public foo Bar {
     get { /* ... your code ... */ }
     set { /* ... your code ... */ }
  }

  public event EventHandler BarChanged;

基于此,我认为您的问题是,您正在尝试使用字段-public Signature Signature;-尝试使用属性.

Based on this I think your problem is that you are trying to use a field - public Signature Signature; - try using a property instead.

我认为您正在寻找的绑定模式也是不常见的OneWayToSource而不是TwoWay

I think the binding mode you are looking for is also the unusual OneWayToSource instead of TwoWay

这篇关于Mvvmcross绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆