2017-03-28 1 views
0

En utilisant MvvmCross et Xamarin.Android est-il possible de lier la propriété IsEnabled d'un ToolItem Toolbar à une valeur booléenne dans un viewmodel? Si oui, comment est-il fait?Comment lier la barre d'outils MenuItem.IsEnabled avec MvvmCross et Xamarin.Android

+0

Il est possible de lier tout membre public du contrôle Android à une propriété de votre ViewModel. Il peut vous aider à lire la section pertinente du wiki si vous avez du mal à y parvenir: https://github.com/MvvmCross/MvvmCross/wiki/databinding –

Répondre

0

Je crois qu'il est impossible pour l'instant de lier Android IMenuItem.IsEnabled à une valeur booléenne sur un viewmodel car IsEnabled est en lecture seule et a changé l'état activé d'un élément de menu nécessite un appel à SetIsEnabled(bool).

J'ai travaillé autour de cette limitation en ajoutant un gestionnaire d'événements pour MvxViewModel.PropertyChanged dans l'activité/fragment. Tous mes viewmodels héritent de MvxViewModel donc je vais partager d'une façon cela peut être accompli. La plupart de mon application est mis en œuvre avec des fragments, donc mon exemple reflète que (dans mon code actuel, je l'ai mis plus de cela dans une base Fragment classe, mais je voulais garder les choses simples):

public class MyViewModel : MvxViewModel 
{ 
    public bool MenuItemIsEnabled { 
     get{return _menuItemIsEnabled;} 
     set{SetProperty(ref _menuItemIsEnabled, value); 
    } 
} 

[MvxFragment(typeof(MainViewModel), Resource.Id.content_frame, true)] 
[Register(nameof(MyFragment))] 
public class MyFragment : MvxFragment 
{ 
    private Toolbar Toolbar; 

    //menuitem whose enabled state should change with viewmodel property 
    private IMenuItem MyMenuItem;  

    public new MyViewModel ViewModel 
    { 
     get { return (MyViewModel)base.ViewModel; } 
     set { base.ViewModel = value; } 
    } 

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    { 
     var view = base.OnCreateView(inflater, container, savedInstanceState); 

     //we'll need the Toolbar later when we set up the IsEnabled "binding" 
     Toolbar = view.FindViewById<Toolbar>(Resource.Id.toolbar); 

     return view; 
    } 

    public override void OnViewModelSet() 
    { 
     base.OnViewModelSet(); 

     ViewModel.PropertyChanged += ViewModel_PropertyChanged; 
    } 

    public override void OnCreateOptionsMenu(IMenu menu, MenuInflater inflater) 
    { 
     base.OnCreateOptionsMenu(menu, inflater); 

     //create the menu based on a menu resource 
     inflater.Inflate(Resource.Menu.my_menu, menu); 

     //save a reference to the menu item so we can update it when the viewmodel changes 
     MyMenuItem = menu.FindItem(Resource.Id.my_menu_item); 

     //set the initial enabled state based on the viewmodel 
     MyMenuItem.SetEnabled(ViewModel.MenuItemIsEnabled); 
    } 

    private void ViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
    { 
     //when ViewModel.MenuItemIsEnabled is updated, update the menuitem enabled state as well 
     if (e.PropertyName == nameof(ViewModel.MenuItemIsEnabled)) 
      BinContentsMenuItem?.SetEnabled(ViewModel.MenuItemIsEnabled); 
    } 
} 

Cette devrait être considéré comme pseudocode, car il essaie de démontrer les concepts généraux que j'ai utilisés pour contourner mon problème original.

+0

Vous pouvez également utiliser WeakSubscribe sur votre ViewModel pour obtenir uniquement les modifications pour: cette propriété spécifique. Vous n'avez alors plus besoin de vous désabonner des événements pour ne pas perdre de mémoire. – Cheesebaron

+0

Ok, ça a vraiment bien fonctionné et ça rend tellement plus facile, merci :) – GabeFC