Home > database >  Load ViewModel before running codebehind
Load ViewModel before running codebehind

Time:02-18

I'm trying to dynamically create tabs for a iOS app.

I've passed through a variable, with shell navigation, that loads items from a database for which we create a tab for each object.

The problem I have is that the codebehind runs before the shell navigation has passed the variable from the viewmodel to the codebehind.

Viewmodel:

{
    [QueryProperty(nameof(Number), nameof(Number))]

    public class TabbedPageViewModel : BaseViewModel
    {

        private int _Number;

        public TabbedPageViewModel()
        {


        }

        public int Number
        {
            get => _Number;
            set => SetProperty(ref _Number, value);
            
        }
    }

Codebehind:

public partial class TabbedPage : TabbedPage
    {

        TabbedPageViewModel _viewModel;
        
        public TabbedPage()
        {
            BindingContext = _viewModel = new TabbedPageViewModel();
            InitializeComponent();
            LoadTabs();
            
        }

        private void LoadTabs()
        {
            
            var results = Database.GetAsync(_viewModel.Number).Result;
            foreach (var _result in results)
            {
                var from = _result.A;
                var to = _result.B;
                var _title = from   "-"   to;
                this.Children.Add(new ContentPage { Title = _title });
            }
        }

    }

How can I delay the codebehind so that the shell navigation sets the Number variable before LoadTabs() runs?

CodePudding user response:

I ended up using Messaging Center:

CodeBehind

public TabbedPage()
        {
            
            InitializeComponent();
            BindingContext = _viewModel = new TabbedPageViewModel();

            MessagingCenter.Subscribe<TabbedPageViewModel>(this, "NumberChanged", (sender) =>
            { LoadTabs(); }
            );

        }

ViewModel:

public int Number
        {
            get => _number;
            set
            {
                SetProperty(ref _number, value);
                MessagingCenter.Send<TabbedPageViewModel>(this, "NumberChanged");
            }        
        }

CodePudding user response:

Your problem is because your not initializing before BindingContext.

public TabbedPage()
        {
            InitializeComponent();
            BindingContext = _viewModel = new TabbedPageViewModel();          
            LoadTabs();
            
        }

Send number using constructor:

int num = 1;
await Navigation.PushAsync (new TabbedPage (num));

then

public TabbedPage(int num)
       {
           InitializeComponent();
           BindingContext = _viewModel = new TabbedPageViewModel();          
           LoadTabs(num);

       }

private void LoadTabs(int num)
       {
           
           var results = Database.GetAsync(num).Result;
           foreach (var _result in results)
           {
               var from = _result.A;
               var to = _result.B;
               var _title = from   "-"   to;
               this.Children.Add(new ContentPage { Title = _title });
           }
       }

Or if using shell:


[QueryProperty(nameof(Number), "number")]
public partial class TabbedPage : TabbedPage
    {
        private int _Number;

        public int Number
        {
            get => _Number;
            set => SetProperty(ref _Number, value);
            
        }
 public TabbedPage()
        {
           InitializeComponent();
            BindingContext = _viewModel = new TabbedPageViewModel();
            
            LoadTabs();
            
        }

private void LoadTabs()
        {
            
            var results = Database.GetAsync(Number).Result;
            foreach (var _result in results)
            {
                var from = _result.A;
                var to = _result.B;
                var _title = from   "-"   to;
                this.Children.Add(new ContentPage { Title = _title });
            }
        }
  • Related