2016-08-22 2 views
0

Ich bin mit einem Problem stecken, wo ich Netzwerkkonnektivität in einer iOS-App überprüfen und versuchen, eine boolesche hasNetworkConnection in meinem View-Controller für seine Ansicht Modell binden.Zwei-Wege-Bindung mit MVVM Cross

View-Controller 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; 
      } 
     } 
    } 
} 

Ich mag würde für die Konnektivität überprüfen, meine iOS-spezifischen Code und binden die boolean Verwendung wieder in eine öffentliche Ansicht Modelleigenschaft.

Ansicht Modell

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; } 
    } 
} 

Ich habe ein Problem mit dieser Codezeile:

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

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

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

if (_networkConnectivity.HasNetworkConnection) bereits null ist, auch wenn ich gesetzt Zweiweg verbindlich. Ich bin neu in MVVM Cross aus diesem Grund Ich weiß nicht, ob meine Vorgehensweise korrekt ist.

Gibt es jemanden, der Hilfe anbieten könnte? Nick

+0

Warum überprüfen Sie nicht, ob '_networkConnectivity.HasNetworkConnection' nicht null ist? Oder setzen Sie einen Standardwert, dh Kein Netzwerkstatus oder etwas? – ViVi

Antwort

0

Sie müssen explizit die Bindung, welche Eigenschaft Sie binden möchten, informieren Sie Ihren NetworkConnectivity wie:

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

Allerdings ist die Bindung keine Möglichkeit haben, um informiert, dass Ihre NetworkConnectivity Klasse jeder bekommen hat seiner Werte aktualisiert. Daher müssten Sie diese Klasse erweitern, um eine Art von Ereignis zu haben, wo sie benachrichtigt werden können.

Dann müssten Sie eine Target Binding-Klasse schreiben und registrieren.

Lassen Sie uns sagen Sie einfach INotifyPropertyChanged in Ihrer NetworkConnectivity Klasse implementieren:

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

Dann legen Sie die folgende Klasse in Ihrem iOS-Projekt:

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); 
    } 
} 

Dann in Setup.cs Überschreibung FillTargetFactories:

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

    base.FillTargetFactories(registry); 
} 

Jetzt sollte die TwoWay-Bindung funktionieren. Sie sollten auch in der Lage sein, den .For(v => v.HasNetworkConnection) von Ihnen verbindlichen Ausdruck zu entfernen.