RadioGroup returning selected value - xamarin.ios

I have a RadioGroup I created:
Root = new RootElement ("Club 1") {
new Section ("Club Members"){
new StringElement ("P1", "Kyle"),
new StringElement ("P2", "Matt"),
new RootElement("Members", new RadioGroup(0))
{
CreateRoot()
}
}
The RootElement above need to the display the value selected from the RadioGroup.
RootElement CreateRoot ()
{
StringElement se = new StringElement (String.Empty);
MyRadioElement.OnSelected += delegate(object sender, EventArgs e) {
se.Caption = (sender as MyRadioElement).Caption;
var root = se.GetImmediateRootElement ();
root.Reload (se, UITableViewRowAnimation.Fade);
};
return new RootElement (String.Empty, new RadioGroup (0)) {
new Section ("Select Member") {
new MyRadioElement ("No Member Selected"),
new MyRadioElement ("Member 1"),
new MyRadioElement ("Member 2"),
new MyRadioElement ("Member 3")
}
};
}
I have an outside class:
class MyRadioElement : RadioElement {
public MyRadioElement (string s) : base (s) {}
public override void Selected (DialogViewController dvc, UITableView tableView, NSIndexPath path)
{
base.Selected (dvc, tableView, path);
var selected = OnSelected;
if (selected != null)
selected (this, EventArgs.Empty);
}
static public event EventHandler<EventArgs> OnSelected;
}
How do I get the selected value to display back on the parent root element?

I was not deactivating the controller.
class MyRadioElement : RadioElement {
public MyRadioElement (string s) : base (s) {}
public override void Selected (DialogViewController dvc, UITableView tableView, NSIndexPath path)
{
base.Selected (dvc, tableView, path);
var selected = OnSelected;
if (selected != null)
selected (this, EventArgs.Empty);
dvc.DeactivateController(true);
}
static public event EventHandler<EventArgs> OnSelected;
}

Related

Xamarin.iOS adding button programmatically to UITableViewCell- nothing happens when clicking it

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.

Navigating to UIViewController from table cell

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);

MonoTouch NullReferenceException on tableview scroll

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);
}

View is not accessible after ParentViewController.View.AddSubview

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;
}
}
}

MonoTouch.Dialog : Advanced Editing

I'm trying to put together a detail view that is editable, similar to the iPhone default contacts app.
I have a TableView of contacts and I activate an editable detail view when a cell is selected:
public override void Selected (DialogViewController dvc, UITableView tableView, NSIndexPath path)
{
var editingSection = new Section ("Entity") {
new StringElement ("First name", "enter", _entity.FirstName),
new StringElement ("Last name", "enter", _entity.LastName)
};
var root = new RootElement("Entity Entry") {
editingSection
};
var entityEdit = new EntityEdit (root, true);
ConfigEdit (entityEdit);
dvc.ActivateController(entityEdit);
}
void ConfigEdit (DialogViewController dvc)
{
dvc.NavigationItem.RightBarButtonItem = new UIBarButtonItem (UIBarButtonSystemItem.Edit, delegate {
dvc.TableView.SetEditing (true, true);
ConfigDone (dvc);
});
}
void ConfigDone (DialogViewController dvc)
{
dvc.NavigationItem.RightBarButtonItem = new UIBarButtonItem (UIBarButtonSystemItem.Done, delegate {
dvc.TableView.SetEditing (false, true);
ConfigEdit (dvc);
});
}
The behavior that I want to change is in the ConfigEdit method. When I first show the view, the elements in the editing section should be StringElements. When I switch to edit mode, the elements should change to entry Elements because I want the ability to delete the row, or edit the text inside the element.
Is this possible? Is there a better approach to showing read-only elements until edit mode has been set?
You have a couple of options:
a. You can just change the RootElement with an updated RootElement, or update the individual cells with new cells of the proper type of element to get the desired effect. You could do this by parametrizing your creation:
RootElement CreateRoot (bool editable)
{
return new RootElement (...) {
CreateEditableElement ("foo", bar, editable)
}
}
Element CreateEditableElement (string caption, string content, bool editable)
{
return editable ? EntryElement (caption, content) : StringELement (caption, content)
}
Then you need to call ReloadData after the user has tapped the "Edit" button.
The other thing that you could do is to create a new Element that can switch states based on this information. My blog has a tutorial on how to create new elements:
http://tirania.org/monomac/archive/2011/Jan-18.html
Based on Miguel's answer, here is what I did:
public partial class AppDelegate
{
public void DemoAdvancedEditing ()
{
var root = new RootElement ("Todo list") {
new Section() {
new StringElement ("1", "Todo item 1"),
new StringElement ("2","Todo item 2"),
new StringElement ("3","Todo item 3"),
new StringElement ("4","Todo item 4"),
new StringElement ("5","Todo item 5")
}
};
var dvc = new AdvancedEditingDialog (root, true);
AdvancedConfigEdit (dvc);
navigation.PushViewController (dvc, true);
}
void AdvancedConfigEdit (DialogViewController dvc)
{
dvc.NavigationItem.RightBarButtonItem = new UIBarButtonItem (UIBarButtonSystemItem.Edit, delegate {
// Activate editing
// Switch the root to editable elements
dvc.Root = CreateEditableRoot(dvc.Root, true);
dvc.ReloadData();
// Activate row editing & deleting
dvc.TableView.SetEditing (true, true);
AdvancedConfigDone(dvc);
});
}
void AdvancedConfigDone (DialogViewController dvc)
{
dvc.NavigationItem.RightBarButtonItem = new UIBarButtonItem (UIBarButtonSystemItem.Done, delegate {
// Deactivate editing
dvc.ReloadData();
// Switch updated entry elements to StringElements
dvc.Root = CreateEditableRoot(dvc.Root, false);
dvc.TableView.SetEditing (false, true);
AdvancedConfigEdit (dvc);
});
}
RootElement CreateEditableRoot (RootElement root, bool editable)
{
var rootElement = new RootElement("Todo list") {
new Section()
};
foreach (var element in root[0].Elements) {
if(element is StringElement) {
rootElement[0].Add(CreateEditableElement (element.Caption, (element as StringElement).Value, editable));
} else {
rootElement[0].Add(CreateEditableElement (element.Caption, (element as EntryElement).Value, editable));
}
}
return rootElement;
}
Element CreateEditableElement (string caption, string content, bool editable)
{
if (editable) {
return new EntryElement(caption, "todo", content);
} else {
return new StringElement(caption, content);
}
}
}

Resources