与MVVM Cross

时间:2016-08-22 09:46:18

标签: c# ios mvvm mvvmcross

我遇到了一个问题,我正在检查iOS应用中的网络连接,并尝试在我的视图控制器中为其视图模型绑定布尔值hasNetworkConnection。

查看控制器UpdateContentView.cs

// This file has been autogenerated from a class added in the UI designer.

using System;
using MvvmCross.iOS.Views;
using MvvmCross.Binding.BindingContext;
using Training.Core;

namespace EdwardsTraining.IOS
{
    public partial class UpdateContentView : MvxViewController
    {
        public UpdateContentView(IntPtr handle) : base(handle)
        {
        }



        public override void ViewDidLoad()
        {
            base.ViewDidLoad();



            var bindingSet = this.CreateBindingSet<UpdateContentView, UpdateContentViewModel>();
            bindingSet.Bind(NoConnectionView).For(x => x.Hidden).To(vm => vm.HasConnection).WithConversion("ReverseBoolean");
            bindingSet.Bind(UpdateInProgressView).For(x => x.Hidden).To(vm => vm.InProgress).WithConversion("ReverseBoolean");
            bindingSet.Bind(UpdateAvailableView).For(x => x.Hidden).To(vm => vm.HasContentUpdate).WithConversion("ReverseBoolean");
            bindingSet.Bind(CancelButton).For(x => x.Hidden).To(vm => vm.CancelVisible).WithConversion("ReverseBoolean");
            bindingSet.Bind(RetryButton).To(vm => vm.DoRetryUpdate);
            bindingSet.Bind(ConfirmButton).To(vm => vm.DoUpdate);
            //bindingSet.Bind(iOSNetworkConnectivitiy).For(x => x.HasNetworkConnection).To(vm => vm.NetworkConnectivitiy).TwoWay()
                      //.For(vm => vm.HasNetworkConnection);

            bindingSet.Bind(iOSNetworkConnectivitiy).To(vm => vm.NetworkConnectivitiy).TwoWay();
            bindingSet.Apply();

            _iOSnetworkConnectivity = new NetworkConnectivity()
            {
                HasNetworkConnection = Reachability.IsNetworkAvailable()
            };
        }
        private NetworkConnectivity _iOSnetworkConnectivity { get; set; }
        public NetworkConnectivity iOSNetworkConnectivitiy {
            get{return _iOSnetworkConnectivity;}
            set { _iOSnetworkConnectivity = value;
            }
        }
    }
}

我想使用我的iOS特定代码检查连接,并将返回的布尔值绑定到公共视图模型属性。

查看模型

using System;
using System.Threading.Tasks;
using EdwardsTraining.BusinessLayer.Interfaces.Services;
using MvvmCross.Core.ViewModels;
using MvvmCross.Platform;


namespace Training.Core
{
    public class UpdateContentViewModel : BaseViewModel
    {

        private IApplicationContentService _applicationContentService;
        private ITrainingContentService _trainingContentService;

        public bool _isNetworkAvailable { get; set; }


        public UpdateContentViewModel(IApplicationContentService applicationContentService, ITrainingContentService trainingContentService)
        {
            _applicationContentService = applicationContentService ?? Mvx.Resolve<IApplicationContentService>();
            _trainingContentService = trainingContentService ?? Mvx.Resolve<ITrainingContentService>();
            IntialSetup();
        }
        protected void IntialSetup()
        {
            _cancelVisible = false;
            _hasContentUpdate = true;
            _inProgress = false;

        }

        public void SetNoConnection()
        {
            _cancelVisible = true;
            _hasContentUpdate = false;
            _inProgress = false;
        }

        public void SetInProgress()
        {
            _cancelVisible = false;
            HasContentUpdate = false;
            InProgress = true;
        }

        public void SetProgessComplete()
        {
            InProgress = false;
            Task.Run(async () => await FinishedUpdating());
        }

        public async Task UpdateContent()
        {
            if (_networkConnectivity.HasNetworkConnection)
            {
                SetInProgress();

                await _trainingContentService.UpdateTrainingContentAsync();
                await _applicationContentService.UpdateContent();

                SetProgessComplete();
                await FinishedUpdating();
            }
            return;
        }

        public async Task FinishedUpdating()
        {
            Close(this);
        }

        public MvxCommand DoUpdate
        {
            get { return new MvxCommand(async () => await UpdateContent()); }
        }

        public MvxCommand DoRetryUpdate
        {
            get { return new MvxCommand(async () => await UpdateContent()); }
        }

        public MvxCommand CancelUpdate
        {
            get { return new MvxCommand(async () => await FinishedUpdating()); }
        }


        private bool _hasContentUpdate;

        public bool HasContentUpdate
        {
            get { return _hasContentUpdate; }
            set
            {
                _hasContentUpdate = value;
                RaisePropertyChanged(() => HasContentUpdate);
            }
        }

        private bool _hasConnection;

        public bool HasConnection
        {
            get { return _hasConnection; }
            set
            {
                _hasConnection = value;
                RaisePropertyChanged(() => HasConnection);
            }
        }

        private bool _inProgress;

        public bool InProgress
        {
            get { return _inProgress; }
            set
            {
                _inProgress = value;
                RaisePropertyChanged(() => InProgress);
            }
        }

        private bool _cancelVisible;

        public bool CancelVisible
        {
            get { return _cancelVisible; }
            set
            {
                _cancelVisible = value;
                RaisePropertyChanged(() => CancelVisible);
            }
        }

        private NetworkConnectivity _networkConnectivity { get; set; }
        public NetworkConnectivity NetworkConnectivitiy
        {
            get { return _networkConnectivity; }
            set { 
                _networkConnectivity = value; 
                RaisePropertyChanged(() => NetworkConnectivitiy);
            }
        }
    }

    public class NetworkConnectivity
    {
        public bool HasNetworkConnection { get; set; }
    }
}

我对这行代码有疑问:

public async Task UpdateContent()
        {
            if (_networkConnectivity.HasNetworkConnection)
            {
                SetInProgress();

                await _trainingContentService.UpdateTrainingContentAsync();
                await _applicationContentService.UpdateContent();

                SetProgessComplete();
                await FinishedUpdating();
            }
            return;
        }

如果(_networkConnectivity.HasNetworkConnection)已经为空,即使我设置了双向绑定。我是MVVM cross的新手,因此我不知道我的方法是否正确。

有没有人可以提供一些帮助? 尼克

1 个答案:

答案 0 :(得分:0)

您需要明确告诉绑定要绑定在NetworkConnectivity上的属性,如:

bindingSet.Bind(iOSNetworkConnectivitiy).For(v => v.HasNetworkConnection).To(vm => vm.NetworkConnectivitiy).TwoWay();

但是,绑定没有任何方法可以通知您NetworkConnectivity类已更新其任何值。因此,您必须扩展该类以获得某种可以获得通知的事件。

然后,您必须编写并注册Target Binding类。

假设您只是在NetworkConnectivity类中实现了INotifyPropertyChanged:

public class NetworkConnectivity : MvxNotifyPropertyChanged
{
    private bool _hasNetworkConnection;
    public bool HasNetworkConnection { 
        get { return _hasNetworkConnection; }
        set { 
            _hasNetworkConnection = value;
            RaisePropertyChanged();
        }
    }
}

然后在iOS项目中创建以下类:

public class NetworkConnectivityTargetBinding
    : MvxPropertyInfoTargetBinding<NetworkConnectivity>
{
    public NetworkConnectivityTargetBinding(object target, PropertyInfo targetPropertyInfo)
        : base(target, targetPropertyInfo)
    {
        var view = View;
        if (view == null)
        {
            MvxBindingTrace.Trace(MvxTraceLevel.Error, 
               "NetworkConnectivity is null in NetworkConnectivityTargetBinding");
        }
        else
        {
            view.PropertyChanged += HandleValueChanged;
        }
    }

    private void HandleValueChanged(object sender, System.EventArgs e)
    {
        var view = View;
        if (view == null)
            return;
        FireValueChanged(view.HasNetworkConnection);
    }

    public override MvxBindingMode DefaultMode => MvxBindingMode.TwoWay;

    protected override void Dispose(bool isDisposing)
    {
        if (isDisposing)
        {
            var view = View;
            if (view != null)
            {
                view.PropertyChanged -= HandleValueChanged;
            }
        }
        base.Dispose(isDisposing);
    }
}

然后在Setup.cs中覆盖FillTargetFactories:

protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
    registry.RegisterPropertyInfoBindingFactory(typeof(NetworkConnectivityTargetBinding),
                                                typeof(NetworkConnectivity), "HasNetworkConnection");

    base.FillTargetFactories(registry);
}

现在TwoWay绑定应该有效。您还应该能够从绑定表达式中删除.For(v => v.HasNetworkConnection)