Search code examples
c#iosuitableviewxamarinuiviewcontroller

Bind second UITableView on RowClick of first UITableView in the same UIViewController - ios Xamarin


I have two UITableView in the same UIViewController. tblView1 & tblView2.

Both TableViews are bringing data dynamically. Now my problem is: I want to load data in tblView2 on the basis of SelectedRow from tblView1.

For Example, when I select a company name from tblView1, then tblView2 needs to populate the Cars made by that company.

I have rowIndex of my first table (tblView1), but i can't bind my tblView2 from the RowSelected Method of tblView1. I need help in binding my tblView2. How can i do this?

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using CoreGraphics;
using Foundation;
using UIKit;

namespace Tables
{
    public partial class ViewController : UIViewController
    {
        protected ViewController(IntPtr handle) : base(handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        public ViewController()
        {
            //tblView2.Source = new CompanyModelsSource();

            // Note: this .ctor should not contain any initialization logic.
        }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            if (tblView1 != null)
            {
                tblView1.Source = new CarModelsSource();

            }
            // Perform any additional setup after loading the view, typically from a nib.
        }

        public override void DidReceiveMemoryWarning()
        {
            base.DidReceiveMemoryWarning();
            // Release any cached data, images, etc that aren't in use.
        }
    }

    class CompanyModelsSource : UITableViewSource
    {
        private List<Companies> _Companies;
        NSString _cellID = new NSString("TableCell");

        public CompanyModelsSource()
        {
            _Companies = CompanyTableSource.AllCompany();
        }

        public override nint RowsInSection(UITableView tableview, nint section)
        {
            // tell the TableView how many rows to create
            return _Companies.Count;
        }

        public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
        {
        //I can't access my tblView2 in this method. So where i can bind my other UITableView?

            UILabel lblTotalFacilities = new UILabel();
            lblTotalFacilities.Layer.BackgroundColor = UIColor.Blue.CGColor;
            lblTotalFacilities.Frame = new CGRect(305, 200, 1024, 400);

            ViewController vc = new ViewController();
            vc.View.AddSubview(lblTotalFacilities);
        }

        public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
        {
            Company currentCompany = _Companies[indexPath.Row];

            var cell = tableView.DequeueReusableCell(_cellID) as CompanyTableCell;
            if (cell == null) { cell = new CompanyTableCell(_cellID); }

            cell.UpdateCellControlsWithAuditData(currentCompany.Name);

            return cell;
        }
    }

    public class CompanyTableSource
    {
        public CompanyTableSource()
        {
        }

        public static List<Companies> AllCompany()
        {
            CompanyCollection CC = null;

            string path1 = path + "Companies.xml";

            XmlSerializer serializer = new XmlSerializer(typeof(CompanyCollection));

            StreamReader reader = new StreamReader(path1);
            CC = (CompanyCollection)serializer.Deserialize(reader);
            reader.Close();

            List<Companies> comp = CC.CompanyCollection.Cast<Companies>().ToList();
            return comp;
        }
    }

    public class CompanyTableCell : UITableViewCell
    {
        UILabel nameLabel;
        public CompanyTableCell(NSString cellId) : base(UITableViewCellStyle.Default, cellId)
        {
            SelectionStyle = UITableViewCellSelectionStyle.Gray;
            ContentView.BackgroundColor = UIColor.FromRGB(54, 194, 36);

            var newFont = UIFont.SystemFontOfSize(12);

            nameLabel = new UILabel();
            nameLabel.Font = newFont;

            ContentView.AddSubviews(new UIView[] { nameLabel });
        }


        public void UpdateCellControlsWithAuditData(string Name)
        {
            nameLabel.Text = Name;

        }

        public override void LayoutSubviews()
        {
            base.LayoutSubviews();
            nameLabel.Frame = new CGRect(10, 0, 350, 33);

        }
    }
}

TablesViewController


Solution

  • Hope this helps. Created everything in a single file for simplicity.

    public partial class ViewController : UIViewController
    {
        public ViewController() : base("ViewController", null)
        {
        }
    
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            // Perform any additional setup after loading the view, typically from a nib.
    
            var companySource = new CompanyTableSource();
            tblView1.Source = companySource;
    
            companySource.ItemSelected += OnCompanyItemSelected;
        }
    
        // This will handle the ItemSelected event
        // Here you will retrieve the data for the second UITableView
        void OnCompanyItemSelected(object sender, Company e)
        {
            // you can do it this way
            tblView2.Source = new CarTableSource(e.Id);
    
            List<Car> cars = GetCarsByCompanyId(e.Id);
    
            // or this way
            tblView2.Source = new CarTableSource(cars);
        }
    
        List<Car> GetCarsByCompanyId(int id)
        {
            // Your logic to get the data goes here
            throw new NotImplementedException();
        }
    }
    
    public class CompanyTableSource : UITableViewSource
    {
        // You can use the whole object or just an integer (companyId)
        public event EventHandler<Company> ItemSelected;
    
        public IList<Company> Items { get; private set; } = new List<Company>();
    
        public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
        {
            var item = Items[indexPath.Row];
    
            ItemSelected?.Invoke(this, item);
        }
    
        public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
        {
            // Do your implementation
            throw new NotImplementedException();
        }
    
        public override nint RowsInSection(UITableView tableview, nint section)
        {
            return Items.Count;
        }
    }
    
    public class CarTableSource : UITableViewSource
    {
    
        public IList<Car> Items { get; private set; } = new List<Car>();
    
        public CarTableSource(int companyId)
        { 
            // Get your data based on the companyId
        }
    
        // Or pass in the data already retrieved (I prefer this method)
        public CarTableSource(IList<Car> cars)
        {
            Items = cars;
        }
    
        public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
        {
            // Do your implementation
            throw new NotImplementedException();
        }
    
        public override nint RowsInSection(UITableView tableview, nint section)
        {
            return Items.Count;
        }
    }