I am using Monotouch to develop iPad app.
Here is my scenario:
I Created Tabbed base application.
e.g. Home, Admin, Reports....etc
Home tab is UIViewController.
I want three section inside Home Tab:
e.g. Category(Table view with navigation control (reason to use navigation because we have subcategories inside Category) beside Category Table, Items of selected category(Other Table view) and right hand side is detail view of Selected ITEM.
Here is what i did....
Dynamically create two tableview controller and added to main view controller.
HomeViewController.cs:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
RootViewController rvc = new RootViewController("",UITableViewStyle.Grouped);
// navigation controller will manage the views displayed and provide navigation buttons
navigationController = new UINavigationController();
navigationController.PushViewController(rvc, false);
navigationController.TopViewController.Title ="Category";
navigationController.View.Frame = new RectangleF (0, 50, (50), (600));
// Main window to which we add the navigation controller to
this.View.AddSubview(navigationController.View);
itemtable.Delegate = new TableViewDelegate (list);
itemtable.DataSource = new TableViewDataSource (list);
// Perform any additional setup after loading the view, typically from a nib.
}
=====================================================
RootViewController:
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Drawing;
namespace DVPNTN_MobileApp
{
[MonoTouch.Foundation.Register("RootViewController")]
public partial class RootViewController : UITableViewController
{
public List<string> RootData = new List<string> { "Group1", "Group2" };
MonoTouch.UIKit.UINavigationController navigationControllerItem;
string SelectedGroup;
// Allow us to set the style of the TableView
public RootViewController(string selectedGroup, UITableViewStyle style) : base(style)
{
this.SelectedGroup = selectedGroup;
}
class DataSource : UITableViewDataSource
{
static NSString kCellIdentifier = new NSString ("MyIdentifier");
RootViewController tvc;
public DataSource (RootViewController tvc)
{
this.tvc = tvc;
}
public override int RowsInSection (UITableView tableView, int section)
{
return tvc.RootData.Count;
}
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell (kCellIdentifier);
if (cell == null)
{
cell = new UITableViewCell (UITableViewCellStyle.Default, kCellIdentifier);
}
cell.TextLabel.Text = tvc.RootData.ElementAt(indexPath.Row);
cell.Accessory = UITableViewCellAccessory.DetailDisclosureButton;
return cell;
}
}
class TableDelegate : UITableViewDelegate
{
RootViewController tvc;
SubGroupViewController sgvc;
public TableDelegate (RootViewController tvc)
{
this.tvc = tvc;
}
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
string selectedGroup = tvc.RootData.ElementAt(indexPath.Row);
sgvc = new SubGroupViewController(selectedGroup, UITableViewStyle.Grouped);
tvc.NavigationController.PushViewController(sgvc,true);
//tvc.View.RemoveFromSuperview();
//tvc.DidReceiveMemoryWarning();
GC.Collect();
}
}
public override void DidReceiveMemoryWarning ()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
TableView.Delegate = new TableDelegate (this);
TableView.DataSource = new DataSource (this);
RootVIewItemController rvc1 = new RootVIewItemController(SelectedGroup,UITableViewStyle.Grouped);
// navigation controller will manage the views displayed and provide navigation buttons
navigationControllerItem = new UINavigationController();
navigationControllerItem.PushViewController(rvc1, false);
navigationControllerItem.TopViewController.Title = SelectedGroup + " " + "Item List";
navigationControllerItem.View.Frame = new RectangleF (0, 300, (50),(700));
//this.View.AddSubview(navigationControllerItem.View);
//rvc1.View.EnableInputClicksWhenVisible = true;
//this.ParentViewController.AddChildViewController(navigationControllerItem);
**> Problem is here --- subview is successfully added to parent view but it's not accessible, mean items are there but we can't touch cell or row???????**
ParentViewController.View.AddSubview(navigationControllerItem.View);
GC.Collect();
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
// Return true for supported orientations
return true;
}
}
}
********** ItemViewController **
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace DVPNTN_MobileApp
{
[MonoTouch.Foundation.Register("RootVIewItemController")]
public partial class RootVIewItemController : UITableViewController
{
public List<string> RootData = new List<string> { "Item 1", "Item 2", "Item 3", "Item 4" };
string SelectedGroup;
public RootVIewItemController (string selectedGroup, UITableViewStyle style) : base (style)
{
this.SelectedGroup = selectedGroup;
}
class DataSource : UITableViewDataSource
{
static NSString kCellIdentifier = new NSString ("MyIdentifier");
RootVIewItemController tvc;
public DataSource (RootVIewItemController tvc)
{
this.tvc = tvc;
}
public override int RowsInSection (UITableView tableView, int section)
{
return tvc.RootData.Count;
}
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell (kCellIdentifier);
if (cell == null)
{
cell = new UITableViewCell (UITableViewCellStyle.Default, kCellIdentifier);
}
cell.TextLabel.Text = tvc.RootData.ElementAt(indexPath.Row);
//cell.Accessory = UITableViewCellAccessory.DetailDisclosureButton;
return cell;
}
}
class TableDelegate : UITableViewDelegate
{
RootVIewItemController tvc;
SubGroupViewController sgvc;
public TableDelegate (RootVIewItemController tvc)
{
this.tvc = tvc;
}
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
string selectedGroup = tvc.RootData.ElementAt(indexPath.Row);
Console.WriteLine(
"TableViewDelegate.RowSelected: Label={0}",selectedGroup);
/*
if(sgvc == null)
sgvc = new SubGroupViewController(selectedGroup, UITableViewStyle.Grouped);
tvc.NavigationController.PushViewController(sgvc,true);*/
}
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
TableView.Delegate = new TableDelegate (this);
TableView.DataSource = new DataSource (this);
}
public override void DidReceiveMemoryWarning ()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
}
}
Question:
Is it right way to doing this scenario?
It's work fine but when we add Item view to parent view controller it is not accessible, mean item list are there but cells are not accessible, we can't touch cell and raise even or do scrolling.
Please anybody can help me?
Thanks
I am not completely sure what you wanted to do. I took my best guess and created a sample with two solutions. One solution per tab. The first uses the built-in split view controller. I have read several places the UISplitViewController must be the root of the application. I have broke that rule by adding it as a child of the tab control.
The second creates a custom version of a split control.
using System;
using System.Collections.Generic;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Drawing;
namespace delete04223
{
[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
// class-level declarations
UIWindow window;
UITabBarController tabBarController;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
// create a new window instance based on the screen size
window = new UIWindow (UIScreen.MainScreen.Bounds);
var viewController1 = new MyUISplitViewController ();
var viewController2 = new MyUISplitViewController2 ();
tabBarController = new UITabBarController ();
tabBarController.ViewControllers = new UIViewController [] {
viewController1,
viewController2,
};
window.RootViewController = tabBarController;
// make the window visible
window.MakeKeyAndVisible ();
return true;
}
}
public class MyUISplitViewController : UISplitViewController
{
public MyUISplitViewController ()
{
this.Title = "Native Split View";
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
var viewController1 = new LeftViewController ();
var viewController2 = new DummyViewController ("Pane 1", "Pane 1");
this.ViewControllers = new UIViewController [] {viewController1, viewController2};
this.WeakDelegate = viewController2;
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
return true;
}
}
public class MyUISplitViewController2 : UIViewController
{
public MyUISplitViewController2 ()
{
this.Title = "Custom Split View";
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
var viewController1 = new LeftViewController ();
var viewController2 = new DummyViewController ("Pane 1", "Pane 1");
this.AddChildViewController (viewController1);
this.AddChildViewController (viewController2);
this.View.AddSubview (viewController1.View);
this.View.AddSubview (viewController2.View);
}
public override void ViewDidLayoutSubviews ()
{
base.ViewDidLayoutSubviews ();
RectangleF lRect = this.View.Frame;
RectangleF rRect = lRect;
lRect.Width = .3f * lRect.Width;
rRect.X = lRect.Width + 1;
rRect.Width = (.7f * rRect.Width)-1;
this.View.Subviews[0].Frame = lRect;
this.View.Subviews[1].Frame = rRect;
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
return true;
}
}
public class LeftViewController : UINavigationController
{
public LeftViewController ()
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
MyUITableViewController table = new MyUITableViewController (this);
this.PushViewController (table, false);
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
return true;
}
public override UIViewController PopViewControllerAnimated (bool animated)
{
return base.PopViewControllerAnimated (true);
}
}
public class DummyViewController : UIViewController
{
string _myLabelText = "";
UIToolbar _toolbar;
public DummyViewController (string viewName, string labelText)
{
this.Title = viewName;
this._myLabelText = labelText;
this.View.BackgroundColor = UIColor.White;
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
return true;
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
float center = this.View.Frame.Width / 2f;
UILabel label = new UILabel (new RectangleF (center - 50, 100, 100, 40));
label.Text = this._myLabelText;
label.TextAlignment = UITextAlignment.Center;
label.AutoresizingMask = UIViewAutoresizing.FlexibleMargins;
RectangleF rect = this.View.Frame;
rect.Y = 0;
rect.Height = 44;
_toolbar = new UIToolbar (rect);
_toolbar.AutoresizingMask = UIViewAutoresizing.FlexibleWidth;
this.View.AddSubview (label);
this.View.AddSubview (_toolbar);
}
[Export("splitViewController:willHideViewController:withBarButtonItem:forPopoverController:")]
public void WillHideViewController (UISplitViewController svc, UIViewController vc,
UIBarButtonItem barButtonItem, UIPopoverController pc)
{
barButtonItem.Title = "Menu";
var items = new List<UIBarButtonItem> ();
items.Add (barButtonItem);
if (_toolbar.Items != null)
items.AddRange (_toolbar.Items);
_toolbar.SetItems (items.ToArray (), true);
//popoverController = pc;
}
[Export("splitViewController:willShowViewController:invalidatingBarButtonItem:")]
public void WillShowViewController (UISplitViewController svc, UIViewController vc,
UIBarButtonItem button)
{
// Called when the view is shown again in the split view, invalidating the button and popover controller.
var items = new List<UIBarButtonItem> (_toolbar.Items);
items.RemoveAt (0);
_toolbar.SetItems (items.ToArray (), true);
//popoverController = null;
}
}
internal class MyUITableViewController : UITableViewController
{
static NSString kCellIdentifier = new NSString ("MyIdentifier");
LeftViewController _parent;
public MyUITableViewController (LeftViewController parent) : base (UITableViewStyle.Plain)
{
this.TableView.WeakDelegate = this;
this.TableView.WeakDataSource = this;
this._parent = parent;
}
[Export ("tableView:numberOfRowsInSection:")]
public int RowsInSection (UITableView tableView, int section)
{
if (section == 0)
return 2;
return 3;
}
[Export ("tableView:cellForRowAtIndexPath:")]
public UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell (kCellIdentifier);
if (cell == null)
{
cell = new UITableViewCell (UITableViewCellStyle.Default, kCellIdentifier);
}
cell.TextLabel.Text = GetRowName (indexPath);
return cell;
}
private string GetRowName (NSIndexPath indexPath)
{
string ret;
if (indexPath.Section == 0)
{
ret =
indexPath.Row == 0 ? "Row A" : "Row B";
}
else
{
ret =
indexPath.Row == 0 ? "Row D" :
indexPath.Row == 1 ? "Row E" : "Row F";
}
return ret;
}
[Export ("numberOfSectionsInTableView:")]
public int NumberOfSections (UITableView tableView)
{
return 2;
}
[Export ("tableView:titleForHeaderInSection:")]
public string TitleForHeader (UITableView tableView, int section)
{
if (section == 0)
return "One";
return "Two";
}
[Export ("tableView:didSelectRowAtIndexPath:")]
public virtual void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
Console.WriteLine("Item Selected: Section={0}, Row={1}",indexPath.Section, indexPath.Row);
this._parent.PushViewController (new MySubUITableViewController (), true);
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
return true;
}
}
internal class MySubUITableViewController : UITableViewController
{
static NSString kCellIdentifier = new NSString ("MyIdentifier");
static string [] _names = new string [] {"One", "Two", "Three", "Four", "Five"};
public MySubUITableViewController () : base (UITableViewStyle.Plain)
{
this.TableView.WeakDelegate = this;
this.TableView.WeakDataSource = this;
}
[Export ("tableView:numberOfRowsInSection:")]
public int RowsInSection (UITableView tableView, int section)
{
return 5;
}
[Export ("tableView:didSelectRowAtIndexPath:")]
public virtual void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
Console.WriteLine("Item Selected: Section={0}, Row={1}",indexPath.Section, indexPath.Row);
}
[Export ("tableView:cellForRowAtIndexPath:")]
public UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell (kCellIdentifier);
if (cell == null)
{
cell = new UITableViewCell (UITableViewCellStyle.Default, kCellIdentifier);
}
cell.TextLabel.Text = _names[indexPath.Row];
return cell;
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
return true;
}
}
}
Related
I am trying to learn how to add uiviews programmatically to my UITableViewCell. I know I can add it through the storyboard but I need it to be programmatically.
For testing I have added below code. When I click on the button nothing happens, my test method is never called. What am I missing?
var cell = tableView.DequeueReusableCell(CellIdentifier) as TestCell;
var cellWidth = cell.Frame.Width;
var cellheight = cell.Frame.Height;
UIButton testing = new UIButton();
testing.SetTitle("TestBtn", UIControlState.Normal);
testing.Frame = new CGRect(0, 0, cellWidth, cellheight);
testing.BackgroundColor = UIColor.Green;
testing.TouchUpInside += (sender, e) => { test(); };
testing.UserInteractionEnabled = true;
cell.AddSubview(testing);
return cell;
The key is that the controls should be added on Cell.ContentView.Please refer to my below code in ViewController:
protected ViewController(IntPtr handle) : base(handle) { }
public override void ViewDidLoad()
{
base.ViewDidLoad();
UITableView _tableView = new UITableView(View.Bounds);
string[] data = new string[] { "test1", "test2", "test3" };
_tableView.DataSource = new CustomCellDataSource();
this.View.AddSubview(_tableView);
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
}
public class CustomCellDataSource : UITableViewDataSource
{
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell("111");
if(cell == null)
{
cell = new UITableViewCell(UITableViewCellStyle.Default,"111");
cell.BackgroundColor = UIColor.Green;
}
UIButton testing = new UIButton(UIButtonType.System);
testing.SetTitle("TestBtn", UIControlState.Normal);
testing.BackgroundColor = UIColor.Red;
nfloat w = cell.Frame.Width;
nfloat h = cell.Frame.Height;
testing.Frame = new CoreGraphics.CGRect(0, 0, w, h);
cell.ContentView.AddSubview(testing);
return cell;
}
public override nint RowsInSection(UITableView tableView, nint section)
{
return 4;
}
}
public class CustomCellDelegate: UITableViewDelegate
{
[Export("tableView:heightForRowAtIndexPath:")]
public nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
return 40;
}
}
Reference link.
I'm trying to use UICollectionView but I can't find any samples that I can take advantage of. I needed the UICollectionView by code (without using swift/storyboard/forms). Could you give me a really simple example? For example 2 lines with 2 columns please? Basic stuff just to try to understand how I can implement it.
Thank you
You can refer to Collection Views in Xamarin.iOS doc to check how to use Collection View with Code .And here I will show a sample code to explain how to implement it .
Could you give me a really simple example? For example 2 lines with 2 columns please?
First , need to create a GridLayout :
public class GridLayout : UICollectionViewFlowLayout
{
public GridLayout ()
{
}
public override bool ShouldInvalidateLayoutForBoundsChange (CGRect newBounds)
{
return true;
}
public override UICollectionViewLayoutAttributes LayoutAttributesForItem (NSIndexPath path)
{
return base.LayoutAttributesForItem (path);
}
public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect (CGRect rect)
{
return base.LayoutAttributesForElementsInRect (rect);
}
}
Then you can init the Collection View in ViewDidLoad :
static NSString animalCellId = new NSString("AnimalCell");
List<IAnimal> animals;
animals = new List<IAnimal>();
for (int i = 0; i < 2; i++)
{
animals.Add(new Monkey());
}
// Perform any additional setup after loading the view, typically from a nib.
UICollectionView collectionView = new UICollectionView(new CGRect(0, 0, UIScreen.MainScreen.Bounds.Size.Width, 300), new GridLayout());
collectionView.RegisterClassForCell(typeof(AnimalCell), animalCellId);
collectionView.BackgroundColor = UIColor.Blue;
collectionView.DataSource = new MyCollectionViewDataDelegate(animals);
View.AddSubview(collectionView);
Here you also need to creat a Custom Cell for your needs , this can be modified by yourself :
public class AnimalCell : UICollectionViewCell
{
UIImageView imageView;
[Export("initWithFrame:")]
public AnimalCell(CGRect frame) : base(frame)
{
BackgroundView = new UIView { BackgroundColor = UIColor.Orange };
SelectedBackgroundView = new UIView { BackgroundColor = UIColor.Green };
ContentView.Layer.BorderColor = UIColor.LightGray.CGColor;
ContentView.Layer.BorderWidth = 2.0f;
ContentView.BackgroundColor = UIColor.White;
ContentView.Transform = CGAffineTransform.MakeScale(0.8f, 0.8f);
imageView = new UIImageView(UIImage.FromBundle("placeholder.png"));
imageView.Center = ContentView.Center;
imageView.Transform = CGAffineTransform.MakeScale(0.7f, 0.7f);
ContentView.AddSubview(imageView);
}
public UIImage Image
{
set
{
imageView.Image = value;
}
}
[Export("custom")]
void Custom()
{
// Put all your custom menu behavior code here
Console.WriteLine("custom in the cell");
}
public override bool CanPerform(Selector action, NSObject withSender)
{
if (action == new Selector("custom"))
return true;
else
return false;
}
}
The MyCollectionViewDataDelegate also need to be created:
public class MyCollectionViewDataDelegate : UICollectionViewDataSource
{
private List animals;
public MyCollectionViewDataDelegate(List<IAnimal> animals)
{
this.animals = animals;
}
public override nint NumberOfSections(UICollectionView collectionView)
{
return 2;
}
public override nint GetItemsCount(UICollectionView collectionView, nint section)
{
return animals.Count;
}
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
var animalCell = (AnimalCell)collectionView.DequeueReusableCell(animalCellId, indexPath);
var animal = animals[indexPath.Row];
animalCell.Image = animal.Image;
return animalCell;
}
}
You can find that animalCell should be registed when init Collection View .
Then effect :
This is the sample link for reference .
I've run into a bit of a strange problem that I'm not sure how to fix. In my iOS project I have my TableViewCell, and TableSource, my TableSource is supposed to fill each cell with information like:
private Dictionary<string, List<Item>> savedItemList;
protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
{
//var foo = savedItemList.ElementAt(indexPath.Section).Value;
//var Item = foo[indexPath.Row];
NSString cellIdentifier;
cellIdentifier = CellsIdentifier.Key;
var cell = (MyTableViewCell)TableView.DequeueReusableCell(cellIdentifier, indexPath);
return cell;
}
public override nint NumberOfSections(UITableView tableView)
{
return savedItemList.Count;
}
public override string TitleForHeader(UITableView tableView, nint section)
{
return savedItemList.Keys.ElementAt((int)section);
}
So far, the headers and everything work no problem, but I'm not sure how to actually bind the data in from inside the cell. Currently I have
public partial class MyTableViewCell : MvxTableViewCell
{
public static readonly NSString Key = new NSString("MyTableViewCell");
public static readonly UINib Nib;
protected MyTableViewCell(IntPtr handle) : base(handle)
{
SelectionStyle = UITableViewCellSelectionStyle.None;
this.DelayBind(() =>
{
var set = this.CreateBindingSet<MyTableViewCell, Item>();
set.Bind(LBL_NAME)
.To(item => item.Name)
.Apply();
});
// Note: this .ctor should not contain any initialization logic.
}
}
But when I load that view, I receive:
MvxBind:Warning: 8.03 Unable to bind: source property source not found Property:Name on KeyValuePair`2
MvxBind:Warning: 8.03 Unable to bind: source property source not found Property:Name on KeyValuePair`2
And I'm left with the default label text. How do I go about setting my binding to read the data from a Dict?
How did you configure your ViewModel? You should bind your TableView.Source's ItemsSource to your ViewModel, then set your data there:
Here is my binding code in the View:
var source = new TableSource(TableView);
TableView.Source = source;
TableView.RowHeight = 120f;
TableView.ReloadData();
var set = this.CreateBindingSet<FirstView, FirstViewModel>();
set.Bind(source).For(s => s.ItemsSource).To(vm => vm.ItemsGroup);
set.Apply();
The ViewModel may be like this:
public class FirstViewModel : MvxViewModel
{
public FirstViewModel()
{
// Emulate three groups here.
ItemsGroup = new List<SessionGroup>();
for (int i=0; i<3; i++)
{
var list = new List<Item>();
for (int j=0; j<10; j++)
{
list.Add(new Item { Name = "Section:" + i + "Item" + j });
}
ItemsGroup.Add(new SessionGroup("section" + i, list));
}
}
private List<SessionGroup> _ItemsGroup;
public List<SessionGroup> ItemsGroup
{
get
{
return _ItemsGroup;
}
set
{
_ItemsGroup = value;
RaisePropertyChanged(() => ItemsGroup);
}
}
}
public class Item
{
public string Name { set; get; }
}
public class SessionGroup : List<Item>
{
public string Key { get; set; }
public SessionGroup(string key, List<Item> items) : base(items)
{
Key = key;
}
}
After this binding, we can present the TableView. here is my MvxTableViewSource:
public class TableSource : MvxTableViewSource
{
private static readonly NSString CellIdentifier = new NSString("MyTableViewCell");
public TableSource(UITableView tableView)
: base(tableView)
{
tableView.SeparatorStyle = UITableViewCellSeparatorStyle.None;
tableView.RegisterNibForCellReuse(UINib.FromName("MyTableViewCell", NSBundle.MainBundle),
CellIdentifier);
}
protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
{
return TableView.DequeueReusableCell(CellIdentifier, indexPath);
}
protected override object GetItemAt(NSIndexPath indexPath)
{
var _sessionGroup = ItemsSource.ElementAt(indexPath.Section) as SessionGroup;
if (_sessionGroup == null)
return null;
return _sessionGroup[indexPath.Row];
}
public override nint NumberOfSections(UITableView tableView)
{
return ItemsSource.Count();
}
public override nint RowsInSection(UITableView tableview, nint section)
{
var group = ItemsSource.ElementAt((int)section) as SessionGroup;
return group.Count();
}
public override string TitleForHeader(UITableView tableView, nint section)
{
var group = ItemsSource.ElementAt((int)section) as SessionGroup;
return string.Format($"Header for section {group.Key}");
}
}
Update:
If you want to bind your ItemsSource to a Dictionary<>, just modify the GetItemAt() event:
protected override object GetItemAt(NSIndexPath indexPath)
{
return savedItemList.Values.ToList()[indexPath.Section][indexPath.Row];
}
public override nint NumberOfSections(UITableView tableView)
{
if (ItemsSource != null)
{
savedItemList = (Dictionary<string, List<Item>>)ItemsSource;
return savedItemList.Count();
}
return 0;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
if (ItemsSource != null)
{
savedItemList = (Dictionary<string, List<Item>>)ItemsSource;
return savedItemList.Values.ToList()[(int)section].Count;
}
return 0;
}
It point out the Model which will be used in cell class.
I update the demo too, please check it.
I am new to xamarin ios. I am trying to navigate from table cell to present uiviewcontroller.But in my RowSelected method which is in table source class throws "system.nullreference exception" .I am using storyboard and this is my code.
This is my app starting point viewcontroller code
namespace PopulatingTableView
{
public partial class PopulatingTableViewViewController : UIViewController
{
// UITableView table;
public PopulatingTableViewViewController (IntPtr handle) : base (handle)
{
}
public override void DidReceiveMemoryWarning ()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
#region View lifecycle
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
button.TouchUpInside += (object sender, EventArgs e) => {
this.NavigationController.PushViewController(new Listview(),true);
};
}
public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
}
public override void ViewDidAppear (bool animated)
{
base.ViewDidAppear (animated);
}
public override void ViewWillDisappear (bool animated)
{
base.ViewWillDisappear (animated);
}
public override void ViewDidDisappear (bool animated)
{
base.ViewDidDisappear (animated);
}
#endregion
}
}
And this my table viewcontroller codes.
namespace PopulatingTableView
{
public partial class Listview : UITableViewController
{
UISearchBar search;
UITableView table;
Listview _list;
public Listview()
{
}
public Listview (IntPtr handle) : base (handle)
{
search = new UISearchBar ();
search.BackgroundColor = UIColor.Clear;
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
table = new UITableView(View.Bounds);
customcell ();
RectangleF search_frame = new RectangleF (0,80,300,30);
search = new UISearchBar (search_frame);
View.Add (search);
View.Add(table);
}
public void customcell()
{
List<TableItems> tableItems = new List<TableItems>();
tableItems.Add(new TableItems("Vegetables") { ImageName = "date.png" });
tableItems.Add(new TableItems("Fruits") { ImageName = "date.png" });
tableItems.Add(new TableItems("Flower Buds") { ImageName = "date.png" });
tableItems.Add(new TableItems("Legumes") { ImageName = "date.png" });
tableItems.Add(new TableItems("Bulbs") {ImageName = "date.png" });
tableItems.Add(new TableItems("Tubers") { ImageName = "date.png" });
table.Source = new TableSource(tableItems,_list);
}
}
}
This is table source class code.In this class i am getting null reference exception in Rowselected method
namespace PopulatingTableView {
public class TableSource : UITableViewSource {
List<TableItems> tableItems;
Listview parentcontroller ;
NSString cellIdentifier = new NSString("TableCell");
public event Action<int> OnRowSelect;
public TableSource ()
{
}
public TableSource (List<TableItems> items,Listview viewcontroller)
{
tableItems = items;
parentcontroller = viewcontroller;
}
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
// new UIAlertView("Row Selected", tableItems[indexPath.Row].Heading, null, "OK", null).Show();
parentcontroller.NavigationController.PushViewController (new _navigated_page(),true);
tableView.DeselectRow (indexPath, true);
}
public override nint RowsInSection (UITableView tableview, nint section)
{
return tableItems.Count;
}
public override UITableViewCell GetCell (UITableView tableView,NSIndexPath indexPath)
{
CustomVegeCell cell = tableView.DequeueReusableCell (cellIdentifier) as CustomVegeCell;
if (cell == null) {
cell = new CustomVegeCell (cellIdentifier);
}
cell.UpdateCell (UIImage.FromFile ("Images/" + tableItems [indexPath.Row].ImageName)
// , tableItems[indexPath.Row].SubHeading
,tableItems[indexPath.Row].Heading );
return cell;
}
}
}
And this is custom cells code.
namespace PopulatingTableView {
public class CustomVegeCell: UITableViewCell {
UILabel headingLabel; //subheadingLabel;
UIImageView imageView;
UIButton talk,date;
public CustomVegeCell (NSString cellId) : base (UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.White;
imageView = new UIImageView();
talk = new UIButton () {
Font = UIFont.FromName("Times New Roman", 10f),
BackgroundColor = UIColor.Orange,
};
date = new UIButton () {
Font = UIFont.FromName("Times New Roman", 10f),
BackgroundColor = UIColor.Green,
};
headingLabel = new UILabel () {
Font = UIFont.FromName("Times New Roman", 14f),
TextColor = UIColor.Black,
BackgroundColor = UIColor.Clear
};
ContentView.Add (headingLabel);
ContentView.Add (imageView);
ContentView.Add (talk);
ContentView.Add (date);
}
public void UpdateCell ( UIImage image,string caption)
{
imageView.Image = image;
headingLabel.Text = caption;
talk.SetTitle ("Talk", UIControlState.Normal);
talk.SetTitleColor (UIColor.White, UIControlState.Normal);
date.SetTitle ("Date", UIControlState.Normal);
date.SetTitleColor (UIColor.White, UIControlState.Normal);
}
public override void LayoutSubviews ()
{
base.LayoutSubviews ();
imageView.Frame = new RectangleF(5, 5, 33, 25);
headingLabel.Frame = new RectangleF(65, 5, 100, 25);
talk.Frame = new RectangleF(200, 8, 50, 25);
date.Frame = new RectangleF(260, 8, 50, 25);
}
}
}
This is the present uiviewcontroller code.When i trying to navigate from Listview.cs to _navigated_page.cs "nullreferenceexception" arised.Could anyone say what is problem with my code
namespace PopulatingTableView
{
partial class _navigated_page : UIViewController
{
UILabel label1,label2,label3;
public _navigated_page (IntPtr handle) : base (handle)
{
}
public _navigated_page()
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad ();
var frame = new RectangleF(10, 60, 300, 110);
label1 = new UILabel(frame);
label1.Text = "New Label";
View.Add (label1);
var frame1 = new RectangleF(10, 90, 300, 110);
label2 = new UILabel(frame1);
label2.Text = "New Label";
View.Add (label2);
var frame2 = new RectangleF(10, 120, 300, 110);
label3 = new UILabel(frame2);
label3.Text = "New Label";
View.Add (label3);
}
}
}
Thanks in advance.
You never initialize _list, so you are always passing a null reference in your constructor:
table.Source = new TableSource(tableItems,_list);
Instead, do this:
table.Source = new TableSource(tableItems, this);
In my app i simply trying to add a checkmark to the selected row. I have around 20 items in my row and want to show a checkmark for the selected row. When i scroll to the bottom of the page and select a row it is throwing NullReferenceException. I have checkmark code reference from here
using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.ObjCRuntime;
using System.Collections.Generic;
namespace SampleApp
{
public partial class FirstViewController : UITableViewController
{
DataSource dataSource;
public FirstViewController () : base ("FirstViewController", null)
{
Title = NSBundle.MainBundle.LocalizedString ("First", "First");
TabBarItem.Image = UIImage.FromBundle ("first");
}
public override void DidReceiveMemoryWarning ()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
// Add Table
TableView.Source = dataSource = new DataSource (this);
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
// Return true for supported orientations
return (toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown);
}
class DataSource : UITableViewSource
{
static readonly NSString CellIdentifier = new NSString ("DataSourceCell");
FirstViewController controller;
private List<String> _listData = new List<String> ();
private NSIndexPath _previousRow;
public DataSource (FirstViewController controller)
{
this.controller = controller;
// POPULATE DISPOSITION LIST
PopulateDatabase();
_previousRow = NSIndexPath.FromRowSection(Settings.SelectedIndex,0);
}
void PopulateDatabase()
{
_listData.Add("val1");
_listData.Add("val2");
_listData.Add("val3");
_listData.Add("val4");
_listData.Add("val5");
_listData.Add("val6");
_listData.Add("val7");
_listData.Add("val8");
_listData.Add("val9");
_listData.Add("val10");
_listData.Add("val11");
_listData.Add("val12");
_listData.Add("val13");
_listData.Add("val14");
_listData.Add("val15");
}
// Customize the number of sections in the table view.
public override int NumberOfSections (UITableView tableView)
{
return 1;
}
public override int RowsInSection (UITableView tableview, int section)
{
return _listData.Count;
}
// Customize the appearance of table view cells.
public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell (CellIdentifier);
if (cell == null) {
cell = new UITableViewCell (UITableViewCellStyle.Default, CellIdentifier);
//cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
}
cell.TextLabel.Text = _listData[indexPath.Row];
cell.TextLabel.Font = UIFont.SystemFontOfSize(18);
return cell;
}
// Row Select
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
// Uncheck the previous row
if (_previousRow != null)
tableView.CellAt(_previousRow).Accessory = UITableViewCellAccessory.None;
// Do something with the row
var row = indexPath.Row;
Settings.SelectedIndex = row;
tableView.CellAt(indexPath).Accessory = UITableViewCellAccessory.Checkmark;
//Console.WriteLine("{0} selected",_controller.Items[row]);
_previousRow = indexPath;
// This is what the Settings does under Settings>Mail>Show on an iPhone
tableView.DeselectRow(indexPath,false);
}
// Set row height
public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
return 50f;
}
}
public class Settings
{
public static int SelectedIndex = 0;
}
}
}
I get the exception at line
tableView.CellAt(_previousRow).Accessory =UITableViewCellAccessory.None;
When i debug i found that Accessory
tableView.CellAt(_previousRow).Accessory Unknown member: Accessory
Any idea what is going wrong???
Got the anser
// Row Select
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
// Uncheck the previous row
if (_previousRow != null)
{
NSIndexPath [] temp = tableView.IndexPathsForVisibleRows;
if (temp.Contains(preIndex))
{
tableView.CellAt(_previousRow).Accessory = UITableViewCellAccessory.None;
}
}
// Do something with the row
var row = indexPath.Row;
Settings.SelectedIndex = row;
tableView.CellAt(indexPath).Accessory = UITableViewCellAccessory.Checkmark;
//Console.WriteLine("{0} selected",_controller.Items[row]);
_previousRow = indexPath;
// This is what the Settings does under Settings>Mail>Show on an iPhone
tableView.DeselectRow(indexPath,false);
}