Xamarin.ios UIActivityIndicatorView.StartAnimating重写UIActivityIndicatorView.Hidden绑定

Xamarin.ios UIActivityIndicatorView.StartAnimating重写UIActivityIndicatorView.Hidden绑定,xamarin.ios,xamarin,mvvmcross,Xamarin.ios,Xamarin,Mvvmcross,我正在控制器中创建UIActivityIndicatorView.ViewDidLoad UIActivityIndicatorView spinner = new UIActivityIndicatorView(); spinner.StartAnimating(); spinner.Hidden = true; this.Add(spinner); 然后我用MVVMCross绑定它 var set = this.CreateBindingSet<TipView, TipViewMod

我正在控制器中创建UIActivityIndicatorView.ViewDidLoad

UIActivityIndicatorView spinner = new UIActivityIndicatorView();
spinner.StartAnimating();
spinner.Hidden = true;
this.Add(spinner);
然后我用MVVMCross绑定它

var set = this.CreateBindingSet<TipView, TipViewModel>();
set.Bind(spinner).For(v => v.Hidden).To(vm => vm.IsBusy).WithConversion("Inverse");
var set=this.CreateBindingSet();
set.Bind(spinner).For(v=>v.Hidden).To(vm=>vm.IsBusy).WithConversion(“Inverse”);
当视图最初加载时,UIActivityIndicatorView旋转且可见。这是不正确的,因为在ViewModel的Init()中IsBusy属性被显式设置为False。我可以看到这种情况发生,我可以看到转换器反转值

我知道绑定已正确连接,因为如果我启动一个更新IsBusy属性的命令,指示器将按预期显示和隐藏。只是初始状态不正确

StartAnimating方法似乎会导致隐藏标志被覆盖。如果我不调用StartAnimating,指示器将按预期隐藏和显示。当然,这意味着我有一个非动画 指标

我可以得到一个关于虚拟机的弱引用,听PropertyChanged并调用StartAnimating,但这似乎有点垃圾


有人有更好的想法吗?

您可以做一些选择:

  • 订阅PropertyChanged更改并在事件处理程序中编写自定义代码(如您在问题中所建议的)

  • UIActivityIndicatorView
    继承并编写一个公共
    get;设置属性,该属性在
    集合
    处理程序中提供复合功能(调用
    开始
    隐藏

    public class MyIndicatorView : UIActivityIndicatorView {
          // ctors
    
         private bool _superHidden;
         public bool SuperHidden {
            get { return _supperHidden; }
            set { _superHidden = value; if (!value) StartAnimating() else StopAnimating(); Hidden = value; }
         }
    }
    
  • 提供
    视图
    public
    get;设置set.Bind(this).For(v=>v.MyAdvanced).

         private bool _myAdvanced;
         public bool MyAdvanced {
            get { return myAdvanced; }
            set { myAdvanced = value; if (!value) _spinner.StartAnimating() else _spinner.StopAnimating(); _spinner.Hidden = value; }
         }
    
  • 为Hidden编写一个自定义绑定,它将替换默认功能,并包含组合的
    Start
    Hidden
    调用(有关自定义绑定的更多信息,请参阅两个N+1教程)


  • 在阅读了@slodge的回复后,我走上了弱事件侦听器的道路,运行代码在视图中隐藏和启动动画。复制并粘贴了三次这种方法后,我意识到有些东西必须改变,所以我实现了他的第四个建议,并编写了一个自定义绑定。FWIW这里就是那个自定义绑定

    /// <summary>
    /// Custom Binding for UIActivityIndicator Hidden. 
    /// This binding will ensure the indicator animates when shown and stops when hidden
    /// </summary>
    public class ActivityIndicatorViewHiddenTargetBinding : MvxConvertingTargetBinding
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ActivityIndicatorViewHiddenTargetBinding"/> class.
        /// </summary>
        /// <param name="target">The target.</param>
        public ActivityIndicatorViewHiddenTargetBinding(UIActivityIndicatorView target)
            : base(target)
        {
            if (target == null)
            {
                MvxBindingTrace.Trace(
                                    MvxTraceLevel.Error,
                                    "Error - UIActivityIndicatorView is null in ActivityIndicatorViewHiddenTargetBinding");
            }
        }
    
        /// <summary>
        /// Gets the default binding mode.
        /// </summary>
        /// <value>
        /// The default mode.
        /// </value>
        public override MvxBindingMode DefaultMode
        {
            get { return MvxBindingMode.OneWay; }
        }
    
        /// <summary>
        /// Gets the type of the target.
        /// </summary>
        /// <value>
        /// The type of the target.
        /// </value>
        public override System.Type TargetType
        {
            get { return typeof(bool); }
        }
    
        /// <summary>
        /// Gets the view.
        /// </summary>
        /// <value>
        /// The view.
        /// </value>
        protected UIActivityIndicatorView View
        {
            get { return Target as UIActivityIndicatorView; }
        }
    
        /// <summary>
        /// Sets the value.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="value">The value.</param>
        protected override void SetValueImpl(object target, object value)
        {
            var view = (UIActivityIndicatorView)target;
            if (view == null)
            {
                return;
            }
    
            view.Hidden = (bool)value;
    
            if (view.Hidden)
            {
                view.StopAnimating();
            }
            else
            {
                view.StartAnimating();
            }
        }
    }
    
    //
    ///UIActivityIndicator的自定义绑定已隐藏。
    ///此绑定将确保指示器在显示时设置动画,在隐藏时停止
    /// 
    公共类ActivityIndicatorViewWhiddenTargetBinding:MvxConvertingTargetBinding
    {
    /// 
    ///初始化类的新实例。
    /// 
    ///目标。
    public ActivityIndicator视图,其中包含目标绑定(UIActivityIndicator视图目标)
    :基本(目标)
    {
    if(target==null)
    {
    MvxBindingTrace.Trace(
    MvxTraceLevel.Error,
    “错误-ActivityIndicatorView在ActivityIndicatorView中为空,而ActivityIndicatorView在ActivityIndicatorView中为空”);
    }
    }
    /// 
    ///获取默认绑定模式。
    /// 
    /// 
    ///默认模式。
    /// 
    公共覆盖MvxBindingMode默认模式
    {
    获取{return MvxBindingMode.OneWay;}
    }
    /// 
    ///获取目标的类型。
    /// 
    /// 
    ///目标的类型。
    /// 
    公共覆盖系统。类型TargetType
    {
    获取{return typeof(bool);}
    }
    /// 
    ///获取视图。
    /// 
    /// 
    ///景色。
    /// 
    受保护的UIActivityIndicator视图
    {
    获取{返回目标为UIActivityIndicatorView;}
    }
    /// 
    ///设置值。
    /// 
    ///目标。
    ///价值。
    受保护的覆盖无效SetValueImpl(对象目标,对象值)
    {
    变量视图=(UIActivityIndicatorView)目标;
    如果(视图==null)
    {
    返回;
    }
    view.Hidden=(bool)值;
    if(view.Hidden)
    {
    停止设置动画();
    }
    其他的
    {
    view.StartAnimating();
    }
    }
    }
    
    我尝试了数字2,但无法使控件显示在工具箱中,因此无法将其拖到情节提要上。然后我尝试了4,但似乎需要类似ValueHasChanged事件的内容,以便可以在自定义绑定中使用一些自定义代码进行响应。UIActivityIndicatorView没有此类事件。选项3.T汉克斯。