【问题标题】:Two way binding with MVVM Cross使用 MVVM Cross 的两种方式绑定
【发布时间】:2016-08-24 04:26:39
【问题描述】:

我遇到了一个问题,我正在检查 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;
        }

if (_networkConnectivity.HasNetworkConnection) 已经为空,即使我设置了两种方式绑定。由于这个原因,我是 MVVM cross 的新手,我不知道我的方法是否正确。

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

【问题讨论】:

  • 你为什么不检查_networkConnectivity.HasNetworkConnection是否不为空?或者设置一些默认值,即没有网络状态或什么?

标签: c# ios mvvm mvvmcross


【解决方案1】:

您需要明确告诉绑定您要在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 =&gt; v.HasNetworkConnection)

【讨论】:

    猜你喜欢
    • 2021-03-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    • 2020-05-08
    • 2016-02-27
    • 1970-01-01
    相关资源
    最近更新 更多