I want to open the new View Controller from my first view that is Table View Controller.
First View Controller: TableView Controller with Rows.
Second View Controller: TableView Controller, Detail View Controller for the selected row on the First Table View Controller.
using System;
using System.Collections.Generic;
using System.Text;
using Foundation;
using UIKit;
namespace TourStops.iOS {
class TourStopsTableSource : UITableViewSource {
private List<TourLib.TourStop> _stops;
NSString _cellID = new NSString("TableCell");
FirstViewController _fvc;
public TourStopsTableSource(FirstViewController fvc) {
_stops = TourLib.TourSource.GetAllTourStops();
_fvc = fvc;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
// tell the TableView how many rows to create
return _stops.Count;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) {
TourLib.TourStop currentTourStop = _stops[indexPath.Row];
var cell = tableView.DequeueReusableCell(_cellID) as TourStopTableCell;
if (cell == null) { cell = new TourStopTableCell(_cellID); }
cell.UpdateCellControlsWithTourData(currentTourStop.Name, currentTourStop.Phone);
#region SetupMapButton
string mapUrl = String.Format("http://maps.google.com/maps?q={0}+{1}",
currentTourStop.Latitude,
currentTourStop.Longitude);
cell.MapButton.TouchUpInside += delegate (object sender, EventArgs e)
{
UIApplication.SharedApplication.OpenUrl(new NSUrl(mapUrl));
};
#endregion
cell.CallButton.TouchUpInside += OpenDetailView;
return cell;
}
private void OpenDetailView(object sender, EventArgs e) {
var view = new SecondDetailController();
_parent.NavigationController.PushViewController(view, true);
}
}
}
My FirstViewController Class:
using Foundation;
using System;
using UIKit;
namespace TourStops.iOS
{
public partial class FirstViewController : UIViewController
{
public FirstViewController (IntPtr handle) : base (handle)
{
}
public FirstViewController ()
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
TourStopsTable.Source = new TourStopsTableSource(new FirstViewController ());
}
}
}
You need a reference to the NavigationController. There are multiple ways to do this, but one common patter is when you create your Source, pass in a reference to it's parent VC
ViewController _parent;
public TourStopsTableSource(UIViewController parent) {
_stops = TourLib.TourSource.GetAllTourStops();
_parent = parent;
}
then, assuming your parent VC is contained within a NavigationController,
private void OpenDetailView(object sender, EventArgs e) {
var view = new SomeDetailController();
_parent.NavigationController.PushViewController(view, true);
}
Edit:
In your amended example above, you are doing
TourStopsTable.Source = new TourStopsTableSource(new FirstViewController ());
instead you need to pass a reference to the ALREADY EXISTING VC:
TourStopsTable.Source = new TourStopsTableSource(this);
Related
I am using MVVMCross in my Xamarin application. I am able to display some data in a tableview, Now I need to customise the tableview cell to add accessory and allow user to go to next screen on selection of a row. How can I achieve it?
My code to display the tableview:
public partial class SchoolSelectionView : MvxViewController<SchoolSelectionViewModel>
{
public SchoolSelectionView() : base("SchoolSelectionView", null)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.NavigationController.SetNavigationBarHidden(true,true);
var source = new MvxStandardTableViewSource(tblSchoolSelection, "TitleText Name");
this.CreateBinding(source).To<SchoolSelectionViewModel>(vm => vm.Items).Apply();
this.CreateBinding(source).For(s => s.SelectionChangedCommand).To<SchoolSelectionViewModel>(vm => vm.ItemSelectedCommand).Apply();
tblSchoolSelection.Source = source;
//tblSchoolSelection.Source = new SchoolListTableSource(this.ViewModel.Items, this);
tblSchoolSelection.ReloadData();
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
}
ustomise the tableview cell to add accessory
Create a subclass inherit from MvxTableViewSource and override the GetOrCreateCellFor method.
var source = new MyTableViewSource(tblSchoolSelection, "TitleText Name");
public class MyTableViewSource: MvxStandardTableViewSource {
override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
{
var cell= tableView.DequeueReusableCell(CellIdentifier);
if (cell== null)
{
//xxxx
}
return cell;
}
}
Refer to Custom MvxTableViewCell Without a NIB File
allow user to go to next screen on selection of a row
Just add ShowViewModel in ItemSelectedCommand in viewModel.
private IMvxCommand _itemSelectedCommand;
public IMvxCommand ItemSelectedCommand
{
get
{
_itemSelectedCommand= _itemSelectedCommand?? new MvxCommand(() => ShowViewModel<NextScreenModel>());
return _itemSelectedCommand;
}
}
I m doing a Xamarin iOS project. I have a UITableView I wan't to select a row when I click in a button and display the information linked to the cell selected.
Like this :
I don't know how to pass data from the first controller to the second when I clicked on the button. How can I do that ?
Here is my TableDataSource :
private const string cellIdentifier = "ProductCell";
private ProductListViewController _controller;
private List<Product> _products;
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
ProductCell cell = (ProductCell)tableView.DequeueReusableCell(cellIdentifier);
if (cell == null)
cell = new ProductCell(new NSString(cellIdentifier));
var record = _products[(int)indexPath.Row];
cell.UpdateCell(record.Image, indexPath.Row);
cell.Tag = indexPath.Row;
return cell;
}
Here is my product custom cell :
public partial class ProductCell : UITableViewCell
{
public static readonly NSString Key = new NSString("ProductCell");
public ProductCell(IntPtr handle) : base(handle)
{
}
public ProductCell(NSString cellId)
{
}
public void UpdateCell(string imageName, nint tag)
{
this.ProductImage.Image = UIImage.FromBundle(imageName);
this.MoreBtn.Tag = tag;
}
}
Edit :
Here is my code for the navigation, I will place it in the action button method. But for now I don't know where to create this method :
var storyboard = UIStoryboard.FromName("Main", null);
var controller = storyboard.InstantiateViewController("ProductDetailViewController") as ProductDetailViewController;
// Here I Will pass the data to the controller
_controller.NavigationController.PushViewController(controller, true);
In GetCell--
cell.yourbtn.Tag = indexPath.Row;
cell.getDetailButton.TouchUpInside -= handler;
cell.getDetailButton.TouchUpInside += handler;
Here is code for button event handler
void handler(Object sender, EventArgs args)
{
nint tag = btn.Tag;
var storyboard = UIStoryboard.FromName("Main", null);
var controller = storyboard.InstantiateViewController("ProductDetailViewController") as ProductDetailViewController;
// datatopass = yourlistofdata[tag]; Here I Will pass the data to the controller -
_controller.NavigationController.PushViewController(controller, true);
}
I am trying to build an self-sizing UITableView Cell. After googled, I found this tutorial: https://pontifex.azurewebsites.net/self-sizing-uitableviewcell-with-uitextview-in-ios-8/ which is quite good.
In swift, it's saying that tableView?.BeginUpdates can update the size of the custom cell. But It seems not working in xamarin ios.
Could someone help me on that? Many Thanks!
using System;
using Foundation;
using UIKit;
using CoreGraphics;
namespace Ma
{
public partial class DataInput : UITableViewCell
{
public string title { get; set;}
public static readonly UINib Nib = UINib.FromName ("DataInput", NSBundle.MainBundle);
public static readonly NSString Key = new NSString ("DataInput");
public string value { get; set;}
public DataInput (IntPtr handle) : base (handle)
{
}
public static DataInput Create ()
{
return (DataInput)Nib.Instantiate (null, null) [0];
}
public void Populate()
{
this.Title.Text = this.title;
if (!string.IsNullOrEmpty(value)) {
this.Input.Text = this.value;
}
}
public string GetInputValue()
{
return this.Input.Text;
}
public UITableView GetTableView()
{
UITableView table = null;
UIView view = this.Superview;
if (view != null) {
table = (UITableView)view.Superview;
}
return table;
}
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
this.Input.ScrollEnabled = false;
this.Input.Delegate = new DataInputDelegate ();
}
public override void SetSelected (bool selected, bool animated)
{
base.SetSelected (selected, animated);
if (selected) {
this.Input.BecomeFirstResponder ();
} else {
this.Input.ResignFirstResponder ();
}
}
}
public partial class DataInputDelegate : UITextViewDelegate
{
public override void Changed (UITextView textView)
{
var size = textView.Bounds.Size;
var newSize = textView.SizeThatFits (new CGSize (size.Width, size.Height));
if (size.Height != newSize.Height) {
UITextView.AnimationsEnabled = false;
UITableViewCell input = (UITableViewCell)textView.Superview.Superview;
UITableView tableView = (UITableView)input.Superview.Superview;
// This is the place of updating custom cell size, but It's not working now.
tableView.BeginUpdates ();
tableView.EndUpdates ();
UITextView.AnimationsEnabled = true;
var thisIndexPath = tableView.IndexPathForCell (input);
tableView.ScrollToRow (thisIndexPath, UITableViewScrollPosition.Bottom, false);
}
}
}
}
BTW, I am using autolayout and set
TableView.EstimatedRowHeight = 50;
TableView.RowHeight = UITableView.AutomaticDimension;
And I have done the following setting as well.
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
if (indexPath.Row == 0) {
return 80.0f;
}
return UITableView.AutomaticDimension;
}
Many thanks if someone can guide me!
Based on constraints placed on view, then autolayout will work. The code works fine after I set up the constraints of each components.
I am trying to perform a segue (with added properties) to a detail view controller when a custom cell in my UICollectionView is highlighted. I am a little stuck on how to achieve this as I cannot use PerformSegue from the subclassed UICollectionViewSource, and I cannot seem to get the selected cell from the UICollectionView.
Here's an abridged version of what I have so far:
Collection Source:
public class ProductCollectionDataSource : UICollectionViewSource
{
public ProductCollectionDataSource()
{
Products = new List<FeedItem>();
}
public List<FeedItem> Products { get; set; }
public override void ItemUnhighlighted(UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = (MultiColumnCell)collectionView.CellForItem(indexPath);
cell.Alpha = 1.0f;
// Perform segue here, passing this cell's data...?
}
}
UIViewController:
public partial class DashboardViewController : UIViewController
{
private ProductCollectionDataSource _dataSource;
public override void ViewDidLoad()
{
_dataSource = new ProductCollectionDataSource();
CollectionView.Source = _dataSource;
GetProducts();
}
private async void GetProducts()
{
_dataSource.Products = new List<FeedItem>(await API.FeedService.Get());
CollectionView.ReloadData();
}
}
So, how can I trigger the segue in the UIViewController, based on the selected cell in the UICollectionView?
You could pass in a reference to your controller and then use that to do the Segue:
public class ProductCollectionDataSource : UICollectionViewSource
{
WeakReference<DashboardViewController> _dvc;
public List<FeedItem> Products { get; set; }
public ProductCollectionDataSource(DashboardViewController parentVc)
{
Products = new List<FeedItem>();
_dvcRef = new WeakReference<DashboardViewController>(parentVc);
}
public override void ItemUnhighlighted(UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = (MultiColumnCell)collectionView.CellForItem(indexPath);
cell.Alpha = 1.0f;
if (_dvcRef.TryGetTarget(out DashboardViewController dashboardVc){
dashboardVc.PerformSegue("Identifier");
}
}
}
}
Set your segue in storyboard (drag & drop)
Open the right panel to add a segue identifier (basically a string like "CustomSegue")
Use the collectionView delegate (didSelectItemAtIndexPath:) to trigger the user tap on a cell
call [self performSegueWithIdentifier:#"CustomSegue" owner:self]
Implement the method prepareForSegue in the controller that manages the UICollectionVIew
Check if [segue.identifier isEqualToString:#"CustomSegue"]
If so, then get the segue.destinationViewController (which is supposed to be your DetailViewController
Pass any property you wish (segue.destinationViewController.property = propertyIWantToPass)
Manually Segue from your ViewController to the Detail View Controller.
SetUp the Segue in the -(void)prepareForSegue method as usual.
Then call it manually where- and whenever you see fit:
-(void)yourCall{
[self performSegueWithIdentifier:#"yourSegueIdentifier" sender:self];
}
I have a tableView that contains a few UITextView controls. When the user taps on one of these the text inside should be selected so that any keyboard input immediately replaces the original content.
I cannot get the text inside a UITextView selected using this code:
txtQuantity.SelectAll (new NSObject(NSObjectFlag.Empty));
as this code only shows the menu "Select | Select All' without the text being actually selected.
Has someone gotten this to work?
EDIT:
The code below select the text inside the txtQuantity control, BUT ONLY IF the UIAlert is show first! Why is this?
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
txtQuantity.TouchDown += txtQuantityHandleTouchDown;
txtQuantity.EditingDidBegin += delegate {
txtQuantity.ExclusiveTouch=true;
UIAlertView uv = new UIAlertView("","OK",null,"OK",null);
uv.Show ();
};
}
void txtQuantityHandleTouchDown (object sender, EventArgs e)
{
txtQuantity.SelectAll (this);
txtQuantity.Selected = true;
}
If all code within the txtQuality.EditingBegin delegate is commented out, the HandleTouchDown event does not fire.
I am not sure that this is what you are going for but I put together a quick sample.
The problem I was having is with calling SelectAll in EditingDidBegin. I had to make a call to BeginInvokeOnMainThread to get the select to work. I am not sure if it is a problem with the event not happening on the main thread or you simply need to make an async call on the main thread.
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace SelectText
{
[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
// class-level declarations
UIWindow window;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
// create a new window instance based on the screen size
window = new UIWindow (UIScreen.MainScreen.Bounds);
window.RootViewController = new MyTableViewController ();
// make the window visible
window.MakeKeyAndVisible ();
return true;
}
}
public class MyTableViewController : UITableViewController
{
public override void LoadView ()
{
base.LoadView ();
this.TableView.DataSource = new TableViewDataSource ();
}
private class TableViewDataSource : UITableViewDataSource
{
private class EditCell : UITableViewCell
{
UITextField _field;
public EditCell () : base (UITableViewCellStyle.Default, "mycell")
{
_field = new UITextField (this.Bounds);
_field.AutoresizingMask = UIViewAutoresizing.All;
_field.BackgroundColor = UIColor.Clear;
_field.ShouldReturn = delegate {
_field.ResignFirstResponder ();
return true;
};
_field.EditingDidBegin += delegate {
this.BeginInvokeOnMainThread ( delegate {
_field.SelectAll (this);
});
};
_field.Text = "Some Text";
this.Add (_field);
}
public override void LayoutSubviews ()
{
base.LayoutSubviews ();
_field.Frame = this.Bounds;
}
}
#region implemented abstract members of UITableViewDataSource
public override int RowsInSection (UITableView tableView, int section)
{
return 2;
}
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell ("mycell");
if (cell == null)
{
cell = new EditCell ();
}
cell.SelectionStyle = UITableViewCellSelectionStyle.None;
return cell;
}
#endregion
}
}
}