2015-01-12 2 views
2

Я создаю UIActivityIndicatorView в моем Controller.ViewDidLoadUIActivityIndicatorView.StartAnimating перекрывая UIActivityIndicatorView.Hidden связывание

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

Когда View изначально загружает UIActivityIndicatorView является спиннинг и видны. Это неверно, поскольку для свойства IsBusy явно установлено значение False в Init() ViewModel. Я вижу, что это происходит, и я вижу, что Конвертер инвертирует значение.

Я знаю, что привязка правильно подключена, потому что, если я запускаю команду, которая обновляет свойство IsBusy, индикатор отображается и скрывается, как я ожидал. Это неправильное исходное состояние.

Метод StartAnimating, по-видимому, вызывает переопределение скрытого флага. Если я не вызываю StartAnimating индикаторы, скрывает и показывает, как ожидалось. Конечно, это означает, что у меня есть неанимающий индикатор .

Я могу получить WeakReference для VM, послушать PropertyChanged и вызвать StartAnimating, но это кажется немного мусором.

Есть ли у кого-нибудь лучшие идеи?

ответ

1

После прочтения ответа @ slodge я пошел по дороге Слабый Event Listener и запустил код для Hide и StartAnimating в представлении. Скопировав и вставив этот подход 3 раза, я понял, что что-то изменилось, поэтому я внедрил его четвертое предложение и написал Custom Binding. 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(); 
     } 
    } 
} 
4

Некоторые опции вы можете сделать:

  1. Подписка на изменения PropertyChanged и написать собственный код в обработчик события (как вы предлагаете в вашем вопросе)

  2. Наследовать от UIActivityIndicatorView и написать публичный get;set; (вызывающий Start и Hidden) в обработчике set

    public class MyIndicatorView : UIActivityIndicatorView { 
         // ctors 
    
        private bool _superHidden; 
        public bool SuperHidden { 
         get { return _supperHidden; } 
         set { _superHidden = value; if (!value) StartAnimating() else StopAnimating(); Hidden = value; } 
        } 
    } 
    
  3. Предоставьте View общедоступное свойство get;set; и поместите в него составную функциональность (например, 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; } 
        } 
    
  4. Написать обычай связывания для Hidden, которая заменяет функции по умолчанию и содержит объединенные Start и Hidden звонки (для больше на пользовательских привязок, есть пара N + 1 учебники)

+0

Я пробовал номер 2, но не смог заставить элемент управления появляться на панели инструментов и, следовательно, не мог его перетащить на раскадровку. Затем я попробовал 4, но похоже, что мне нужно что-то вроде события ValueHasChanged, поэтому я могу ответить с помощью некоторого пользовательского кода в пользовательской привязке. У UIActivityIndicatorView таких событий нет. Кровавый iOS. –

+0

вариант 3. Спасибо. –

Смежные вопросы