簡體   English   中英

MvvmCross不綁定

[英]MvvmCross not binding

我正在使用MvvmCross開發Pong。 按住向上和向下按鈕(Android視圖/活動中的按鈕-而非鍵盤按鈕)時,Paddles Y值會更改。 但是,該視圖未在視圖中顯示(槳板保持在一個位置,即使我在控制台日志中看到槳板已上升或下降)。

為什么槳Y值未正確綁定到視圖?

這是代碼:

ViewModel:

using System.Linq;
using System.Text;
using System.Threading;

using Cirrious.MvvmCross.ViewModels;

using Pong.Core.ViewModels;
using Pong.Core.Models;

namespace Pong.Core.ViewModels
{
    public class GamePlayViewModel 
        : MvxViewModel
    {

        private string _hello = "Hello MvvmCross";
        public string Hello
        { 
            get { return _hello; }
            set { _hello = value; RaisePropertyChanged(() => Hello); }
        }

        private int _totalFramesBeenHad;
        public int TotalFramesBeenHad
        { 
            get { return _totalFramesBeenHad; }
            set { _totalFramesBeenHad = value; RaisePropertyChanged(() => TotalFramesBeenHad); }
        }



        private PlayerPaddle _paddle1;
        public int Paddle1
        { 
            get { return _paddle1.Y; }
            set { _paddle1.Y = value; RaisePropertyChanged(() => Paddle1); }
        }

        private ComputerPaddle _paddle2;
        public int Paddle2
        { 
            get { return _paddle2.Y; }
            set { _paddle2.Y = value; RaisePropertyChanged(() => Paddle2); }
        }



        protected StandardBall StandardBall;

        public GamePlayViewModel()
        {
            _paddle1 = new PlayerPaddle();
            _paddle2 = new ComputerPaddle();
            StandardBall = new StandardBall();

        }

        public void UpdatePaddle1()
        {
            switch (_paddle1.DetectWallCollision())
            {
            case "upper":
                _paddle1.UpperWallHit();
                break;
            case "lower":
                _paddle1.LowerWallHit();
                break;
            case "none":
                _paddle1.MoveOneFrame();
                break;
            }
        }

        public void UpdateBall()
        {
            if (StandardBall.DetectWallCollision()) StandardBall.HandleWallCollision();
            StandardBall.MoveOneFrame();
        }

        public void SetPaddleDirection(string direction)
        {
            _paddle1.SetDirection(direction);
        }

        public void StopPaddle()
        {
            _paddle1.StopMoving();
        }
    }
}

子視圖模型(實際使用的一種):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using Pong.Core.ViewModels;
using Pong.Core.Models;
using Pong.Droid.Views;

namespace Pong.Droid.ViewModels
{
    public class GamePlayViewModelAndroid : GamePlayViewModel
    {
        public readonly Timer _dispatcherTimer;

        public GamePlayView gpv;
        public GamePlayViewModelAndroid (GamePlayView gpv)
        {
            this.gpv = gpv;
            TimerCallback timerDelegate = new TimerCallback (Tick);
            _dispatcherTimer = new Timer (timerDelegate, null, 0, 1000/Court.FPS);
        }

        public void Tick(object state)
        {
            UpdatePaddle1();
            gpv.move ();
        }
    }
}

視圖:

using Android.App;
using Android.OS;
using Cirrious.MvvmCross.Droid.Views;
using Cirrious;
using Cirrious.CrossCore;
using Cirrious.MvvmCross.Binding;
using Cirrious.MvvmCross.ViewModels;
using Pong.Droid.ViewModels;
using Android.Content.PM;
using Pong.Droid;
using Android.Views;
using Android.Widget;
using Android.Graphics;
using Android.Content;
using Android.Content.Res;
using Cirrious.MvvmCross.Binding.BindingContext;

using Pong.Core.Models;


namespace Pong.Droid.Views
{
    [Activity(Label = "!PONG!", ScreenOrientation = ScreenOrientation.Landscape)]
    public class GamePlayView : MvxActivity
    {
        private GamePlayViewModelAndroid _viewModel;
        private Button _buttonUp;
        private Button _buttonDown;
        public GameView GameView;
        public LinearLayout ParentLayout;
        public LinearLayout ButtonsLayout;
        public int _paddle1y;
        public int _paddle2y;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            GameView = new GameView (this);
            _viewModel = new GamePlayViewModelAndroid(this);
            SetUpControls ();
            SetUpButtonEvents ();
            SetContentView(ParentLayout);
            DataContext = _viewModel;


            this.ClearAllBindings();
            var set = this.CreateBindingSet<GamePlayView, GamePlayViewModelAndroid>();
            set.Bind(this).For(v => v._paddle1y).To(vm => vm.Paddle1);
            set.Bind(this).For(v => v._paddle2y).To(vm => vm.Paddle2);
            set.Apply();
        }

        void SetUpButtonEvents ()
        {
            _buttonUp.Touch += (s, e) =>  {
                var handled = false;
                if (e.Event.Action == MotionEventActions.Down) {
                    _viewModel.SetPaddleDirection ("up");
                    handled = true;
                }
                else
                    if (e.Event.Action == MotionEventActions.Up) {
                        _viewModel.StopPaddle ();
                        handled = true;
                    }
                e.Handled = handled;
            };
            _buttonDown.Touch += (s, e) =>  {
                var handled = false;
                if (e.Event.Action == MotionEventActions.Down) {
                    _viewModel.SetPaddleDirection ("down");
                    handled = true;
                }
                else
                    if (e.Event.Action == MotionEventActions.Up) {
                        _viewModel.StopPaddle ();
                        handled = true;
                    }
                e.Handled = handled;
            };
        }

        void SetUpControls ()
        {
            _buttonUp = new Button (this);
            _buttonDown = new Button (this);
            ParentLayout = new LinearLayout (this);
            ButtonsLayout = new LinearLayout (this);
            ParentLayout.Orientation = Android.Widget.Orientation.Horizontal;
            ButtonsLayout.Orientation = Android.Widget.Orientation.Vertical;
            ButtonsLayout.AddView (_buttonUp);
            ButtonsLayout.AddView (_buttonDown);
            ParentLayout.AddView (ButtonsLayout);
            ParentLayout.AddView (GameView);
        }

        public void move() {
            //GameView.paddle1y = _viewModel.Paddle1.Y;
            //GameView.paddle2y = _viewModel.Paddle2.Y;
            RunOnUiThread (() => GameView.Invalidate ());
        }
    }

    public class GameView : View {
        private Bitmap _paddleBmp;
        private int _paddle1x; 
        public int _paddle1y;
        private int _paddle2x; 
        public int _paddle2y;
        public GamePlayViewModelAndroid vm;
        public GamePlayView View;

        public GameView(Context context) : base (context) {
            SetPaddleBmp ();
//          this.ClearAllBindings();
//          var set = this.CreateBindingSet<GameView, GamePlayViewModelAndroid>();
//          set.Bind(_paddle1y).To(vm => vm.Paddle1.Y);
//          set.Bind(_paddle2y).To(vm => vm.Paddle2.Y);
//          set.Apply();
            //var set = this.CreateBindingSet<PolicySummaryCell, PolicyComponent<BasePolicy>>();
            //set.Bind(_periodOfInsurance).To(vm => vm.PeriodOfInsurance);
            //set.Bind(_title).To(vm => vm.Title);
            View = (GamePlayView)context;

        }

        void SetPaddleBmp ()
        {
            var paddlebmpTemp = BitmapFactory.DecodeResource (Resources, Resource.Drawable.Icon);
            _paddleBmp = Bitmap.CreateScaledBitmap (paddlebmpTemp, Paddle.Width, Paddle.Height, false);
        }

        protected override void OnDraw(Canvas canvas) {
            canvas.DrawColor(Color.Aqua);
            canvas.DrawBitmap (_paddleBmp, _paddle1x, View._paddle1y, null);
            canvas.DrawBitmap (_paddleBmp, _paddle2x, View._paddle2y, null);
        }

        protected override void OnSizeChanged(int w, int h, int oldw, int oldh) {
            SetUpCourt (w, h);
        }

        void SetUpCourt (int w, int h)
        {
            Court.Width = w;
            Court.Height = h;
            Court.UpperBound = 0;
            Court.LowerBound = h;
            Court.LeftBound = 0;
            Court.RightBound = w;
            ComputerPaddle.X = Court.RightBound - Paddle.Width - 20;
            _paddle2x = ComputerPaddle.X;
            _paddle1x = PlayerPaddle.X;
        }
    }
}

模型:

using System.Diagnostics;

namespace Pong.Core.Models
{
    public class Paddle
    {
        public int Y { get; set; }
        public int VY { get; set; }
        public static readonly int Speed = 600;
        public static readonly int Height = 300;
        public static readonly int Width = 100;

        public void StopMoving()
        {
            VY = 0;
        }

        public void SetDirection(string direction)
        {
            if (direction == "up")
            {
                VY = -Speed;
            }
            else if (direction == "down")
            {
                VY = Speed;
            }
        }

        public string DetectWallCollision()
        {
            if (Y < Court.UpperBound)
            {
                return "upper";
            }
            if (Y > (Court.LowerBound - Paddle.Height))
            {
                return "lower";
            }
            return "none";
        }

        public void UpperWallHit()
        {
            StopMoving();
            Y = Court.UpperBound;
            Debug.WriteLine("You hit the top wall");
        }

        public void LowerWallHit()
        {
            StopMoving();
            Y = Court.LowerBound - Paddle.Height;
            Debug.WriteLine("You hit the bottom wall");
        }

        public void MoveOneFrame()
        {
            Y += VY/Court.FPS;//this should trigger the RaisePropertyChanged(() => Paddle1)
        }
    }

    public class PlayerPaddle : Paddle {
        public static readonly int X = 20;
    }

    public class ComputerPaddle : Paddle {
        public static int X;
    }
}

我認為您的問題在於,您正在更新Paddle.Y字段,但是RaisePropertyChanged()被稱為更新Paddle(在設置中)。 看到不同?

僅當您要在GamePlayViewModel中設置Paddle1和Paddle2屬性的新實例時,該設置程序才會被調用:

Paddle1 = new Paddle(); //will call the setter of Paddle1 property
Paddle1.Y = 90; //would not call the setter property

您需要做的是在更新Paddle1和Paddle2屬性的X和Y值時調用RaisePropertyChanged。

這個問題的答案是,在視圖上,要以編程方式將字段綁定到viewModel,該字段必須是具有getter和setter的屬性。 像這樣。 在視圖中:

public int _paddle1y { get; set; }
public int _paddle2y { get; set; }

我不知道為什么會這樣。 我認為這是MvvmCross中的一個錯誤。 但是也許有一個合理的理由。

而不是直接調用_paddle1,而是調用Paddle1(和2),以便將調用RaisePropertyChanged事件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM