I have the following code set up:
TableView = new UITableView();
TableView.Source = new DataSource();
m_MainScroll.Add(view); // scrollview area
TableView.ReloadData ();
DataSource is simple:
class DataSource : UITableViewSource {
public DataSource ()
{
}
public override int NumberOfSections (UITableView tableView)
{
return 1;
}
public override int RowsInSection (UITableView tableview, int section)
{
return 10;
}
// Customize the appearance of table view cells.
public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
return new UITableViewCell();
}
}
Basically GetCell is never called and I never see the table show up anyway.
Any ideas why?
edit:
Some more potentially relevant code:
(in ViewDidLoad):
m_MainScroll = new UIScrollView(new RectangleF(0, 0, 320, 372));
m_MainScroll.ContentSize = new SizeF(300, ScrollerHeight);
m_MainScroll.ShowsVerticalScrollIndicator = true;
m_MainScroll.DraggingStarted += DragStarted;
AddComponent(m_MainScroll);
UIToolbar bar = new UIToolbar(new RectangleF(0, 372, 320, 44));
View.Add(bar);
UIBarButtonItem barBut = new UIBarButtonItem();
barBut.Style = UIBarButtonItemStyle.Bordered;
barBut.Title = "Next";
NextButton = barBut;
UIBarButtonItem flexer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);
UIBarButtonItem []items = new UIBarButtonItem[2];
items[0] = flexer;
items[1] = barBut;
bar.Items = items;
AddComponent(bar);
public void AddComponent(UIView view)
{
m_Components.Add(view);
View.Add(view);
}
Where m_Components is just a list of UIView and is really only used to defocus controls which have the keyboard on.
Related
I am making an app for iOS using Xamarin I had some trouble with UITableViews and found this tutorial: https://learn.microsoft.com/en-us/xamarin/ios/user-interface/controls/tables/populating-a-table-with-data
I created a new project and followed what they did, but it doesn't work for me. I must be doing something wrong, but I can't figure out what.
Could someone take a look and see why the TableView doesn't show up?
BasicViewController:
public class BasicTableViewController : UIViewController
{
private UIView view;
public override void ViewDidLoad()
{
base.ViewDidLoad();
var table = new UITableView(View.Bounds);
table.Source = new BasicTableSource("aaaaaaaaa", "bbbbb", "cccccccc", "ddddddddddddd", "eeeee");
Add(table);
}
public override void LoadView()
{
view = new UIView()
{
BackgroundColor = UIColor.White,
};
View = view;
}
}
BasicTableViewSource:
public class BasicTableSource : UITableViewSource
{
private readonly string[] items;
public BasicTableSource(params string[] items)
{
this.items = items;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell("cell");
if (cell == null)
cell = new UITableViewCell(UITableViewCellStyle.Default, "cell");
cell.TextLabel.Text = items[indexPath.Row];
return cell;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return items.Length;
}
}
AppDelegate:
[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
public override UIWindow Window { get; set; }
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
Window = new UIWindow(UIScreen.MainScreen.Bounds);
Window.RootViewController = new BasicTableViewController();
Window.MakeKeyAndVisible();
return true;
}
}
What the simulator looks like when running this project:
What the simulator looks like
Cause:
When you override the method LoadView.It seems that you forgot to set the Frame of view.So the size of view will with Height as 0 and Width as 0.
Solution:
Set the frame of view as the size of screen.
public override void LoadView()
{
view = new UIView()
{
Frame = UIScreen.MainScreen.Bounds,
BackgroundColor = UIColor.White,
};
View = view;
}
I have Xamarin.iOS project, where is I use TableView
Here is tableView source code
public class ExperienceSourceNew: UITableViewSource
{
private UINavigationController primNav { get; set; }
private UITableView tableView { get; set; }
List<Experience> TableItems;
ExperienceViewControllerNew _owner;
static NSString cellIdentifier = new NSString("newcell_id");
public ExperienceSourceNew(List<Experience> items, ExperienceViewControllerNew owner, UINavigationController nav)
{
TableItems = items;
_owner = owner;
primNav = nav;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
if (TableItems.Count == 0)
{
var noDataLabel = new UILabel
{
Text = "No Experiences at your location at this time. Try to change destination",
TextColor = UIColor.Black,
TextAlignment = UITextAlignment.Center,
LineBreakMode = UILineBreakMode.WordWrap,
Lines = 0
};
tableview.BackgroundView = noDataLabel;
tableview.SeparatorStyle = UITableViewCellSeparatorStyle.None;
return TableItems.Count;
}
else
{
tableview.BackgroundView = null;
tableview.SeparatorStyle = UITableViewCellSeparatorStyle.SingleLine;
return TableItems.Count;
}
}
public override async void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
var selectedExperience = await ExperienceMethods.GetSelectedTour(TableItems[indexPath.Row].id);
if (selectedExperience == "Saved")
{
ExperienceDetailViewController ExperienceDetailController = primNav.Storyboard.InstantiateViewController("ExperienceDetailViewController") as ExperienceDetailViewController;
primNav.PushViewController(ExperienceDetailController, true);
}
else
{
UIAlertController okAlertController = UIAlertController.Create("", "Cannot select this experience", UIAlertControllerStyle.Alert);
okAlertController.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
}
tableView.DeselectRow(indexPath, true);
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = (ExperienceCellNew)tableView.DequeueReusableCell(cellIdentifier, indexPath);
Experience item = TableItems[indexPath.Row];
cell.UpdateCell(item);
return cell;
}
I use custom Cell for TableView, so here is code for it
public ExperienceCellNew (IntPtr handle) : base (handle)
{
}
internal void UpdateCell(Experience experience)
{
var image_url = "https://xplorpal.com/" + experience.cover_image.img_path + "/150x150/" + experience.cover_image.img_file;
ExperienceTitleNew.Text = experience.title;
ExperiencePriceNew.Text = "$" + experience.price;
NSUrlSession session = NSUrlSession.SharedSession;
var dataTask = session.CreateDataTask(new NSUrlRequest(new NSUrl(image_url)), (data, response, error) =>
{
if (response != null)
{
DispatchQueue.MainQueue.DispatchAsync(() =>
{
ExperienceImageNew.Image = UIImage.LoadFromData(data);
});
}
});
dataTask.Resume();
}
}
My problem, that images not appears on View load, I have text in labels, but don't have images. If I scroll TableView, images are appears in cells.
Where can be problem and how to solve it?
Table Views with large number of rows display only a small fraction of their total items at a given time.It's efficient for table views to ask for only the cells for row that are being displayed Therefor on scrolling the table view, the cells get re-used and the data within the cell is repopulated.
Since you are using a downloaded image it appears to be slow.
You can try loading the image of the exact size as the image view within the cell.
This is similar to your issue
And also assigning the image to imageview on main thread and make it synchronous as UI changes require synchronous access to main thread.
As an alternative, you can use FFImageLoading which will let you do this
ImageService.LoadUrl(image_url).Into(ExperienceImageNew);
I want to create a listview with multiple fields and image. I am used table view for developing list view, but I wont get the correct design.
Please help me...
Here is my code
class TableViewSource : UITableViewSource
{
List<Sample> tabledata;
public TableViewSource(List<Sample> items)
{
tabledata = items;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell("cell") as CustomVegeCell;
if (cell == null)
cell.UpdateCell(tabledata[indexPath.Row].CaseID
, tabledata[indexPath.Row].Description
, UIImage.FromFile("right_arrow.png"));
return cell;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return tabledata.Count;
}
public override void WillDisplay(UITableView tableView, UITableViewCell cell, NSIndexPath indexPath)
{
if (indexPath.Row == tabledata.Count - 1)
{
//Reload your data here
}
}
}
Here is my ViewController.cs
List<Sample> _itemdata;
public ViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
DAtaBinding();
mainTable.Source = new TableViewSource(_itemdata);
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
}
public void DAtaBinding()
{
_itemdata = new List<Sample>() { { new Sample { CaseID="CQ964C",Description="Aswathy"} },
{ new Sample { CaseID="CQ964C",Description="Anu"}},
{ new Sample { CaseID="CQ964C",Description="Anu"}},
{ new Sample { CaseID="CQ964C",Description="Anu"}},
{ new Sample { CaseID="CQ964C",Description="Anu"}},
{ new Sample { CaseID="CQ964C",Description="Anu"}},
};
}
}
Here is my custom tableviewcell
CustomVegeCell.cs
public class CustomVegeCell : UITableViewCell
{
UILabel headingLabel, subheadingLabel;
UIImageView imageView;
public CustomVegeCell(NSString cellId) : base(UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.FromRGB(218, 255, 127);
imageView = new UIImageView();
headingLabel = new UILabel()
{
Font = UIFont.FromName("Cochin-BoldItalic", 22f),
TextColor = UIColor.FromRGB(127, 51, 0),
BackgroundColor = UIColor.Clear
};
subheadingLabel = new UILabel()
{
Font = UIFont.FromName("AmericanTypewriter", 12f),
TextColor = UIColor.FromRGB(38, 127, 0),
TextAlignment = UITextAlignment.Center,
BackgroundColor = UIColor.Clear
};
ContentView.AddSubviews(new UIView[] { headingLabel, subheadingLabel, imageView });
}
public void UpdateCell(string caption, string subtitle, UIImage image)
{
imageView.Image = image;
headingLabel.Text = caption;
subheadingLabel.Text = subtitle;
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
imageView.Frame = new CGRect(ContentView.Bounds.Width - 63, 5, 33, 33);
headingLabel.Frame = new CGRect(5, 4, ContentView.Bounds.Width - 63, 25);
subheadingLabel.Frame = new CGRect(100, 18, 100, 20);
}
}
After adding the custom tableviewcell i got an exception in the GetCell method
I want this design for my screen
You have to new a class inherit from UITableViewCell, and create custom cell layouts in it.
In this scenario you need three labels and a arrow image, and adjust their frame as demonstrated.
Toturial here.
Sample here.
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);
}
}
}
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 whay
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 retreived. (I preffer 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;
}
}
I'm trying to apply an event to a cell in order to specify the TouchesBegan method.
cell.TouchesBegan += OnTouchesBegan;
But TouchesBegan is a method group and not an event.
How do I add custom behavior to a Cells TouchesBegan() method in monotouch?
[Register("MenuView")]
public class MenuView : ViewControllerBase
{
private new MenuViewModel ViewModel { get { return (MenuViewModel)base.ViewModel; } }
public override void ViewDidLoad()
{
base.ViewDidLoad();
// this ensures the sliding panel doesn't fill the entire view.
var frame = View.Frame;
frame.Width = 300;
View.Frame = frame;
var chapters = ViewModel.Chapters;
//var listHeight = (chapters.Count*40);
var navigationList = new UITableView(new RectangleF(0, 50, 300, 300))
{
Source = new NavigationTableSource(chapters)
};
Add(navigationList);
}
}
public class NavigationTableSource : UITableViewSource
{
private readonly IList<ChapterViewModel> _chapters;
private const string CellIdentifier = "NavigationCell";
public NavigationTableSource(IList<ChapterViewModel> chapters)
{
_chapters = chapters;
}
public override int RowsInSection(UITableView tableview, int section)
{
return _chapters.Count;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell(CellIdentifier) ??
new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier);
// if there are no cells to reuse, create a new one
cell.TextLabel.Text = _chapters[indexPath.Row].Title;
cell.TouchesBegan += OnTouchesBegan;
return cell;
}
}
TouchesBegan is a method that you can override by subclassing UITableViewCell:
public class CustomCell : UITableViewCell
{
public CustomCell(UITableViewCellStyle style, NSString reuseIdentifier) : base(style, reuseIdentifier)
{
}
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
// do something
base.TouchesBegan(touches, evt);
}
}
Then use your subclass when creating a cell:
var cell = tableView.DequeueReusableCell(CellIdentifier) ??
new CustomCell(UITableViewCellStyle.Default, CellIdentifier);
So the way I was able to manage this was to SubClass my UITableViewSource. In there I overrode RowSelected(UITableView tableView, NSIndexPath indexPath)
public class NavigationTableSource : UITableViewSource
{
private readonly IList<ChapterViewModel> _chapters;
private const string CellIdentifier = "NavigationCell";
public NavigationTableSource(IList<ChapterViewModel> chapters)
{
_chapters = chapters;
}
public override int RowsInSection(UITableView tableview, int section)
{
return _chapters.Count;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
// todo: This is where we're going to load up the appropriate chapter.
new UIAlertView("Row Selected", _chapters[indexPath.Row].Title, null, "OK", null).Show();
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell(CellIdentifier) ??
new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier);
// if there are no cells to reuse, create a new one
cell.TextLabel.Text = _chapters[indexPath.Row].Title;
return cell;
}
}