我遇到了一个问题,我正在检查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的新手,因此我不知道我的方法是否正确。
有没有人可以提供一些帮助? 尼克
答案 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)
。