Xamarin Forms Binding Context and Bindings

13,133

I think in BuildTabs you want something more like:

FuturePage.BindingContext = RootPage.Future;

Instead of

FuturePage.SetBinding(ListView.ItemsSourceProperty, "Future");

Since your "FuturePage" is not a ListView but a ContentPage and you are setting a BindingContext not assigning a binding.

Share:
13,133
Chad Bonthuys
Author by

Chad Bonthuys

Senior C# developer for DPO|Paygate in the Fintech space

Updated on June 04, 2022

Comments

  • Chad Bonthuys
    Chad Bonthuys about 2 years

    What Im Trying to Achieve:

    I have a Xamarin forms application that retrieves data via an API call, this data is set to the GamesResultModel and bound to a public property in the .APP, the data is then displayed in a listview. Now I have got it working when using multiple pages each binding to the data they require however I only want to use one page that is instantiated multiple times and the binding source and page title is set when instantiated.

    Problem:

    Im not sure how I can set the binding source of a page when the page is instantiated from the rootpage? I tried the below but it did not work

    public static GamesPageModel Future { get; set; }
    FuturePage.SetBinding(ListView.ItemsSourceProperty, "Future");
    

    Code Example:

    public class RootPage : TabbedPage
    {
    
        public static GamesPageModel History { get; set; }
    
        public static GamesPageModel Current { get; set; }
    
        public static GamesPageModel Future { get; set; }
    
     public RootPage()
        {
            ShowLoginDialog();
            buildTabs();
        }
    

    From the rootpage I instantiate a new instance of the GamesPage for each timespan:

        private void buildTabs()
        {
            var historyPage = new GamesPage();
            historyPage.Title = "History";
            historyPage.SetBinding(ListView.ItemsSourceProperty, "History");
    
            var todayPage = new GamesPage();
            todayPage.Title = "Current";
            todayPage.SetBinding(ListView.ItemsSourceProperty, "Today");
    
            var FuturePage = new GamesPage();
            FuturePage.Title = "Future";
            FuturePage.SetBinding(ListView.ItemsSourceProperty, "Future");
    
            this.Children.Add(todayPage);
            this.Children.Add(historyPage);
            this.Children.Add(futurePage);
    }
    

    Games Result Model where the API Call is set:

    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class GamesResult
      {
    [System.Xml.Serialization.XmlArrayItemAttribute("item", IsNullable = false)]
    public xmlItem[] previous { get; set; }
    
    [System.Xml.Serialization.XmlArrayItemAttribute("item", IsNullable = false)]
    public xmlItem[] current { get; set; }
    
    [System.Xml.Serialization.XmlArrayItemAttribute("item", IsNullable = false)]
    public xmlItem[] future { get; set; }
     }
    
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class xmlItem
     {
    public ushort field_id { get; set; }
    
    public string field_desc { get; set; }
    
    public ushort fk_round_id { get; set; }
    
    public string field_start_time { get; set; }
    
    public byte tee_interval { get; set; }
    
    public byte fk_course_id { get; set; }
    
    public uint field_pin { get; set; }
    
    public ushort fourball_id { get; set; }
    
    public ushort fk_field_id { get; set; }
    
    public ushort fk_course_hole_id_tee_off { get; set; }
    
    public string tee_off_time { get; set; }
    
    public ushort fourball_team_id { get; set; }
    
    public byte team_desc { get; set; }
    
    public ushort fk_fourball_id { get; set; }
    
    public ushort fourball_player_id { get; set; }
    
    public ushort fk_player_mem_id { get; set; }
    
    public byte player_hc { get; set; }
    
    public ushort fk_player_team { get; set; }
    
    public byte fk_player_tee { get; set; }
    
    public ushort round_id { get; set; }
    
    public string round_desc { get; set; }
    
    public ushort fk_tour_id { get; set; }
    
    public string round_date { get; set; }
    
    public ushort tour_id { get; set; }
    
    public string tour_desc { get; set; }
    
    public xmlItemTour_start tour_start { get; set; }
    
    public xmlItemTour_end tour_end { get; set; }
    
    public ushort fk_member_id { get; set; }
    
    public xmlItemCreate_date create_date { get; set; }
    
    public byte fk_comp_typ_id { get; set; }
    
    public byte tour_status { get; set; }
    }
    

    Games Page:

    public class GamesPage : ContentPage
    {
        #region Private Properties
    
        private GamesPageModel viewModel
        {
            get { return BindingContext as GamesPageModel; }
        }
    
        private ListView listView;
        #endregion
        this.Content = new StackLayout()
            {       
                Children ={
                     listView
                }
            };
        }
        public GamesPage()
        {
            this.SetBinding(TitleProperty, "Title");
            listView = new ListView();
            var viewTemplate = new DataTemplate(typeof(GameViewCell));  
            listView.ItemTemplate = viewTemplate;
            listView.SetBinding(ListView.ItemsSourceProperty, "Games");
    

    Games Page Model:

    public class GamesPageModel
    {
        public GamesPageModel()
        {
            Games = new List<xmlItem>();
        }
    
        public string Title { get; set; }
    
        public List<xmlItem> Games { get; set; }
    
    }
    

    Game View Cell:

    public class GameViewCell : ViewCell
    {
        public GameViewCell()
        {
            Label tour_Desc = new Label()
                {
                    Font = Font.BoldSystemFontOfSize(15)
                };
    
              Label round_Desc = new Label();
              Label field_Desc = new Label();
    
            tour_Desc.SetBinding(Label.TextProperty, "tour_desc");
            round_Desc.SetBinding(Label.TextProperty, "round_desc");
            field_Desc.SetBinding(Label.TextProperty, "field_desc");
    
            var layout = new StackLayout();
            layout.Children.Add(tour_Desc);
            layout.Children.Add(round_Desc);
            layout.Children.Add(field_Desc);
    
            this.View = layout;
        }
    
    }
    

    Singleton used to set the data on return of the API call to be utilised anywhere in the application:

    public class App
    {
        private static readonly App instance = new App();
        private LoginResult loginResult;
        private GamesResult gamesResult;
    
        public static App Instance
        {
            get
            {
                return instance;
            }
        }
    
        public LoginResult LoginResult
        {
            get
            {
                return loginResult;
            }
            set
            {
                loginResult = value;
            }
        }
    
        public GamesResult GamesResult
        {
            get
            {
                return gamesResult;
            }
            set
            {
                gamesResult = value;
            }
        }
    }
    

    With a simple implementation with multiple pages this is working as seen by the below example:

            var todayPage = new CurrentGamesPage();
            var historyPage = new HistoryGamesPage();
            var futurePage = new FutureGamesPage();
    
            this.Children.Add(todayPage);
            this.Children.Add(historyPage);
            this.Children.Add(futurePage);
    
    
    public class HistoryGamesPage : ContentPage
    {
        private ListView listView;
    
        public HistoryGamesPage()
        {
            Title = "Current Games";
    
            listView = new ListView();
    
            BindData();
    
            this.Content = new StackLayout()
           {
              Children = {
                  listView
              }
           };
        }
    
        public void BindData()
        {
            if (App.Instance.GamesResult != null)
            {
                try
                {
                    var viewTemplate = new DataTemplate(typeof(GameViewCell));
                    listView.ItemTemplate = viewTemplate;
                    listView.ItemsSource = App.Instance.GamesResult.previous;
                }
                catch(Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }
        }
    
    }