2012-06-27 3 views
3

Je suis nouveau à MvvmCross et j'ai une question.MvvmCross Monotouch C# - Binding Int Propriété - Mode: TwoWay

je remarquai que le code de liaison suivant fonctionne dans un seul sens:

{ this, "{'CurrentIndex':{'Path':'CurrentIndex','Mode':'TwoWay'}}" } 
  • Currentlndex est une Int propriété dans la vue
  • Currentlndex est également une Int propriété dans le ViewModel

De cette façon fonctionne!

  • ViewModel => Voir

Mais pas de cette façon!

  • View => ViewModel

J'ai une collection de ViewControllers et mon objectif était d'appeler un DeleteCommand pour le Currentlndex dans le ViewModel.

Cependant,

"liaisons façon dont Android et Touch 2 sont incomplètes"

Référence: MvvmCross experiences, hindsight, limitations?

Ma conjecture est le mode TwoWay ne fonctionne que pour les contrôles (UILabel, UITextField, ...) mais pas pour les propriétés.

Alors, y a-t-il un bon moyen de le faire fonctionner dans les deux sens? Ou y a-t-il des alternatives à mon problème?

Patrick

Répondre

4

Pour une fixation pour transférer toute valeur entre une vue à une mise ViewModel, il doit accrocher dans un événement lorsque la valeur change.

Dans ViewModel, cet événement est toujours l'événement dans l'interface INotifyProperty.

Dans la vue/activité, un seul motif est utilisé - chaque liaison doit donc être connectée à un événement distinct. Par exemple, le texte sur EditText est connecté à l'aide de l'événement TextChanged (voir MvxEditTextTextTargetBinding.cs) tandis que la valeur d'un SeekBar est connectée à l'aide d'un objet Listener plutôt que d'un événement (voir MvxSeekBarProgressTargetBinging.cs).

Donc, si vous voulez mettre en œuvre cette liaison dans les deux sens pour votre activité, vous pouvez le faire par:

  • déclarant un événement - CurrentIndexChanged - dans votre activité (MyActivity) qui est tiré chaque fois que des changements de currentIndex
  • Déclarez une liaison personnalisée pour votre MyActivity qui relie Currentlndex et programmation CurrentIndexChanged
  • ajouter la liaison personnalisée au registre de liaison lors de l'installation

Par exemple, votre activité pourrait inclure:

public event EventHandler CurrentIndexChanged; 

private int _currentIndex; 
public int CurrentIndex 
{ 
    get { return _currentIndex; } 
    set { _currentIndex = value; if (CurrentIndexChanged != null) CurrentIndexChanged(this, EventArgs.Empty); } 
} 

Et vous pourriez alors déclarer une classe de liaison comme:

public class MyBinding : MvxPropertyInfoTargetBinding<MyActivity> 
{   
    public MyBinding (object target, PropertyInfo targetPropertyInfo) 
     : base(target, targetPropertyInfo) 
    { 
     View.CurrentIndexChanged += OnCurrentIndexChanged; 
    } 

    public override MvxBindingMode DefaultMode 
    { 
     get 
     { 
      return MvxBindingMode.TwoWay; 
     } 
    } 

    private void OnCurrentIndexChanged(object sender, EventArgs ignored) 
    { 
     FireValueChanged(View.CurrentIndex); 
    } 

    protected override void Dispose(bool isDisposing) 
    { 
     base.Dispose(isDisposing); 
     if (isDisposing) 
     { 
      View.CurrentIndexChanged -= OnCurrentIndexChanged; 
     } 
    } 
} 

Et vous auriez besoin de dire au système de fixation à propos de cette liaison dans la configuration comme :

 registry.RegisterFactory(new MvxSimplePropertyInfoTargetBindingFactory(typeof(MyBinding), typeof(MyActivity), "CurrentIndex")); 

Mais ... à un niveau pratique, si vous exploitez en C# plutôt qu'en XML, alors vous feriez mieux d'utiliser C# pour simplement mettre à jour le ViewModel plutôt que d'utiliser la liaison déclarative dans ce cas.

Pour être clair ... dans ce cas, je très probablement écrire juste la propriété d'activité comme:

public int CurrentIndex 
{ 
    get { return _currentIndex; } 
    set { _currentIndex = value; ViewModel.CurrentIndex = value; } 
} 

Ou ... Je considérerais de ne pas avoir cette propriété dans l'activité du tout.


Si elle aide, il y a un peu plus d'informations sur les liaisons personnalisées dans:


Hope this helps! À mon humble avis les liaisons sont là pour vous aider lorsque vous travaillez en XML - vous ne devez pas les utiliser ...

Stuart


MISE À JOUR Si vous allez faire beaucoup de et ceux-ci suivent le même modèle de nom - en utilisant la propriété nommée X avec l'événement EventHandler changé le nom XChanged alors quelque chose comme ça pourrait fonctionner - il utilise la réflexion pour trouver l'événement automagiquement:

public class MyBinding<T> : MvxPropertyInfoTargetBinding<T> 
    where T : class 
{ 
    private readonly PropertyInfo _propertyInfo; 
    private readonly EventInfo _eventInfo; 

    public MyBinding(object target, PropertyInfo targetPropertyInfo) 
     : base(target, targetPropertyInfo) 
    { 
     _propertyInfo = targetPropertyInfo; 
     var eventName = _propertyInfo.Name + "Changed"; 
     _eventInfo = View.GetType().GetEvent(eventName); 
     if (_eventInfo == null) 
     { 
      throw new MvxException("Event missing " + eventName); 
     } 

     if (_eventInfo.EventHandlerType != typeof(EventHandler)) 
     { 
      throw new MvxException("Event type mismatch for " + eventName); 
     } 

     var addMethod = _eventInfo.GetAddMethod(); 
     addMethod.Invoke(View, new object[] { new EventHandler(OnChanged) }); 
    } 

    public override MvxBindingMode DefaultMode 
    { 
     get 
     { 
      return MvxBindingMode.TwoWay; 
     } 
    } 

    private void OnChanged(object sender, EventArgs ignored) 
    { 
     var value = _propertyInfo.GetValue(View, null); 
     FireValueChanged(value); 
    } 

    protected override void Dispose(bool isDisposing) 
    { 
     base.Dispose(isDisposing); 
     if (isDisposing) 
     { 
      var removeMethod = _eventInfo.GetRemoveMethod(); 
      removeMethod.Invoke(View, new object[] { new EventHandler(OnChanged) }); 
     } 
    } 
} 
+0

@Stuart, Dans l'exemple ci-dessus, CurrentIndex est de type int, et MyBinding requiert que T soit le type de référence. Comment pouvez-vous utiliser votre réponse mise à jour? – ttotto

+0

@Stuart, registre.RegisterFactory (nouveau MvxSimplePropertyInfoTargetBindingFactory (typeof (MyBinding ), typeof (MyActivity), "CurrentIndex")); erreur dans MyBinding ttotto

Questions connexes