0
votes

I've been banging my head against this for two days now working with mvvmcross, and having never worked with iOS before I think there's just something I don't understand.

I created my main menu with a UICollectionView in a two-column 3-row grid, each item representing a different location the user can go to on tap. I can override "ItemSelected" from the UICollectionViewSource, but I can't access the actual ViewModel without passing a reference of it into the source on creation....which doesnt feel like the right way to do it to me.

 [MvxRootPresentation(WrapInNavigationController = true)]
    public partial class MainPageView : MvxViewController

    {

    private MenuCollectionSource _menuCollectionSource;
    List<MainMenuItem> menuItems;

    public MainPageViewModel VM
    {
        get { return DataContext as MainPageViewModel; }
    }

    private void SetupMenuCollectionView()
    {
    ......

        collectionView.RegisterNibForCell(MainMenuCollectionViewCell.Nib, MainMenuCollectionViewCell.Key);
        MainMenuItem.Init(menuItems);
        _menuCollectionSource = new MenuCollectionSource(collectionView, MainMenuCollectionViewCell.Key, menuItems);
        _menuCollectionSource.VM = VM; <----doesnt seem right.
        collectionView.Source = _menuCollectionSource;

    public class MenuCollectionSource : MvxCollectionViewSource
    {

        private UICollectionView _collectionView;
        public List<MainMenuItem> Items { get; set; }

        private MainPageViewModel _vm;
        public MainPageViewModel VM
        {
            get { return _vm; }
            set { _vm = value; }
        }

    }

With this method I can override ItemSelected in the ViewSource, and the do something like

( Cell is touched -> 
Depending on cell enum/cell# - >
vm.NavigateToCorrectPage())

While this method works, I don't think its the correct way to handle this situation. So then my next thought was to bind the source like like...(may not be 100%, trying to remember in my head)

set.CreateBinding(_menuCollectionSource) .For(s => s.SelectedCommand) .To(vm => vm.NavigateTo) .CommandParameter(_menuCollectionSource.SelectedItem)

But no matter what I tried, the passed param was always null as if the selected item was never set or the command was being called before it was set.

My CollectionViewCell class is pretty basic

 public enum NavigationLocation
    {
    Search Database,
    Lists,
    etc....
    }
    public partial class MainMenuCollectionViewCell : MvxCollectionViewCell
    {
    public static readonly NSString Key = new NSString("MainMenuCollectionViewCell");
    public static readonly UINib Nib;

        public string MainMenuLabel
        { get { return mainMenuLabel.Text; } }

        public int MainMenuIndexNumber
        { get; set; }

        protected MainMenuCollectionViewCell(IntPtr handle) : base(handle)
        {

        }

        static MainMenuCollectionViewCell()
        {
            Nib = UINib.FromName("MainMenuCollectionViewCell",  NSBundle.MainBundle);
        }

        public static MainMenuCollectionViewCell Create()

        {
            NSArray topLevelObjects = NSBundle.MainBundle.LoadNib("MainMenuCollectionViewCell", null, null);
            MainMenuCollectionViewCell cell = Runtime.GetNSObject(topLevelObjects.ValueAt(0)) as MainMenuCollectionViewCell;
            return cell;
        }

        internal void BindData(string label, string iconBundleName)
        {
             mainMenuLabel.Text = label;
            mainMenuImage.Image = UIImage.FromBundle(iconBundleName);

        }
    }

No binding I've tried in the cell class has actually worked, even adding a UITapGestureRecognizer on creation caused a crash on actual tap. I've run out of ideas, does anyone know what I'm not understanding or missing to actually implement

( Cell is touched -> 
GetCellMenuType - >
CallCorrectCommandFromViewModel)

Thank you

1
Did you find the answer? - Michał Żołnieruk
I tried the implementation you suggested below, and got hit with a NullReferenceException at new MvxCommand<Ios.MainMenuCollectionViewCellViewModel>((selectedItem) => { selectedItem.GoToSearchDatabase(); }); selectedItem is null - Swisscheese

1 Answers

0
votes

Use EventHandler SelectedItemChanged from MvxBaseCollectionViewSource

View

set.Bind(yourCollectionViewSource).For(s => s.SelectionChangedCommand).To(vm => vm.CollectionItemSelected);

ViewModel

public ICommand CollectionItemSelected => new MvxCommand<ItemViewModel>((selectedItem) => { });