Xamarin iOS display detail from UITableview - uitableview

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

Related

Two Button click event in single cell in TableView in iOS(Xamarin)

I am making custom cell in xamarin iOS. In the cell I have two Button which is display in the below figure.
Figure :
Two Button are :
Create Appointment
View Detail
I want to create this two different Button click Event in My Source class so that I can send data to different ViewController for my purpose.
Code :
TableCell class :
public partial class CaseHistoryTableCell : UITableViewCell
{
public static readonly NSString Key = new NSString("CaseHistoryTableCell");
public static readonly UINib Nib;
static CaseHistoryTableCell()
{
Nib = UINib.FromName("CaseHistoryTableCell", NSBundle.MainBundle);
}
public CaseHistoryTableCell(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public static CaseHistoryTableCell Create()
{
return (CaseHistoryTableCell)Nib.Instantiate(null, null)[0];
}
public void BindData(string hospitalLabel, string addressLabel, string drLabel, string patientLabel)
{
this.lbl_hospitalName.Text = hospitalLabel;
this.lbl_address.Text = addressLabel;
this.lbl_drName.Text = drLabel;
this.lbl_patientName.Text = patientLabel;
this.lbl_address.TextColor = UIColor.Clear.FromHexString("#000000", 0.54f);
this.lbl_patientName.TextColor = UIColor.Clear.FromHexString("#000000", 0.54f);
this.lbl_caseDate.TextColor = UIColor.Clear.FromHexString("#000000", 0.54f);
this.lbl_scheDate.TextColor = UIColor.Clear.FromHexString("#000000", 0.54f);
this.lbl_hospitalName.TextColor = UIColor.Clear.FromHexString("#000000", 0.87f);
this.lbl_drName.TextColor = UIColor.Clear.FromHexString("#000000", 0.87f);
this.btn_createAppointment.SetTitleColor(UIColor.Clear.FromHexString("#0072BA", 1.0f), UIControlState.Normal);
this.btn_viewDetail.SetTitleColor(UIColor.Clear.FromHexString("#0072BA", 1.0f), UIControlState.Normal);
}
public override CGRect Frame
{
get
{
return base.Frame;
}
set
{
value.Y += 4;
value.Height -= 2 * 4;
base.Frame = value;
}
}
}
Source Class :
public class CaseHistorySourceClass : UITableViewSource
{
private List<CaseSearchItem> caseSearchItems;
public CaseSearchItem caseSearchItem;
public static event EventHandler RowClicked;
public CaseHistorySourceClass(List<CaseSearchItem> caseSearchItems)
{
this.caseSearchItems = caseSearchItems;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
CaseHistoryTableCell cell = tableView.DequeueReusableCell(CaseHistoryTableCell.Key) as CaseHistoryTableCell ?? CaseHistoryTableCell.Create();
var item = caseSearchItems[indexPath.Row];
cell.BindData(item.Organization, item.Address, item.Doctor, item.UserName);
cell.Layer.MasksToBounds = false;
cell.Layer.CornerRadius = 10.0f;
cell.BackgroundColor = UIColor.White;
cell.SetNeedsLayout();
cell.LayoutIfNeeded();
return cell;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return caseSearchItems.Count;
}
}
My Question :
It is possible to Create two different Button click event in a single Cell.
If yes then How ?
and If No then what is alternative to Perform this type of operation.
Note : I doesn't want to require RowSelected. I only require how to
perform this two different Button click Event.
Don't do such operation on RowSelected
Setting Target with selector will help you out .
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
CaseHistoryTableCell cell = tableView.DequeueReusableCell(CaseHistoryTableCell.Key) as CaseHistoryTableCell ?? CaseHistoryTableCell.Create();
var item = caseSearchItems[indexPath.Row];
// setTag to button to identify in which row button is pressed
cell.btnCreateAppointment.tag=indexPath.Row;
cell.btnViewDetail.tag=indexPath.row;
// set Target to a method
cell.btnCreateAppointment.TouchUpInside += createAppointment;
ell.btnViewDetail.TouchUpInside +=viewDetail;
}
These Method will be called when Press you button
public void createAppointment(object sender, EventArgs e)
{
var row=sender.tag;
}
Second button Clicked event
public void viewDetail(object sender, EventArgs e)
{
var row=sender.tag;
}
i hope this work.
You can do this by adding target action to button from your GetCell method:
first add following in your cell class to make buttons accessible:
public UIButton btnCreateAppointment {
get
{
return this.btn_createAppointment;
}
}
public UIButton btnViewDetail
{
get
{
return this.btn_viewDetail;
}
}
Now from modify your GetCell method to add action target
cell.btnCreateAppointment.tag = indexPath.Row;
cell.btnViewDetail.tag = indexPath.row;
//assign action
cell.btnCreateAppointment.TouchUpInside += (sender, e) =>
{
var row = ((UIButton)sender).Tag;
var item = caseSearchItems[row];
};
cell.btnViewDetail.TouchUpInside += (sender, e) =>
{
var row = ((UIButton)sender).Tag;
var item = caseSearchItems[row];
};

Xamarin ios how to make a self-sizing UITableViewCell while editing

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.

UITableView cuts my table view, cannot view the entire TableView[Xamarin, iOS]

I am trying to make a custom TableView that has big heights, but when i run it i can only access 2 of my 5 rows in the table(in the example i provided)
Here is a screen shot of how i am viewing my table : http://i.imgur.com/1dsPNj5.png
Here is the link to my Table Source : http://pastebin.com/B7U2BEd8
Here is my view controller :
unclass[] lol= new unclass[amount];
for (nint i = 0; i < amount; i++) {
lol [i] = new unclass ();
Console.WriteLine ("item created");
}
UITableView _table;
_table = new UITableView{ Frame = new CoreGraphics.CGRect (0, 30, View.Bounds.Width, 3000),Source= new TableSource(lol) };
_table.SeparatorStyle = UITableViewCellSeparatorStyle.None;
for (nint i = 0; i < amount; i++) {
lol [i].imager = await this.LoadImage (links[i]); //loads image from the net to table
}
View.AddSubview (_table);
}
I really don't understand why this is happening
Your TableSource is not the problem, I tested it with a blank table.
Also as Jason said you will need to change the table's frame height to "View.Bounds.Height - 30" -30 to compensate for your Y position. I created a simple example below that show all 5 cells. So it might be the way that you are adding the table or if there is anything else in the viewController. Are you able to post more of your view controller's code?
using UIKit;
using CoreGraphics;
using System;
using Foundation;
namespace SO_Xam_actvity
{
public class bigTableViewController : UIViewController
{
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
UITableView _table;
_table = new UITableView{ Frame = new CGRect (0, 30, View.Bounds.Width, View.Bounds.Height-30),Source= new TableSource(new [] {1,1,1,1,1}) };
_table.SeparatorStyle = UITableViewCellSeparatorStyle.None;
View.AddSubview (_table);
}
}
public class TableSource : UITableViewSource
{
int[] tableItems;
string cellIdentifier = bigTableViewCell.Key;
public TableSource (int[] items)
{
tableItems = items;
}
public override nint RowsInSection (UITableView tableview, nint section)
{
return tableItems.Length;
}
public override nfloat GetHeightForRow (UITableView tableView, NSIndexPath indexPath)
{
return 200;
}
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell (cellIdentifier) as bigTableViewCell;
if (cell == null) {
cell = new bigTableViewCell();
}
cell.DetailTextLabel.Text = $"{indexPath.Row}";
return cell;
}
}
public class bigTableViewCell : UITableViewCell
{
public static readonly NSString Key = new NSString ("bigTableViewCell");
public bigTableViewCell () : base (UITableViewCellStyle.Value1, Key)
{
TextLabel.Text = "TextLabel";
}
}
}

On a custom UITableViewCell with a button the text disappears sometimes - iOS 7

I've created a custom UITableViewCell with a UIButton in it. In iOS 6 it behaves as expected all the time. In iOS 7 it looks correct after the view is loaded the first time. But after any TableView.ReloadData() the text on the button disappears until I touch the button and swipe away to not trigger the click event.
You can see the described behavior in the movie: http://youtu.be/9SrKfouah7A
ButtonCellNew.cs
using System;
using MonoTouch.UIKit;
using System.Drawing;
namespace B2.Device.iOS
{
public class ButtonCellNew : UITableViewCell
{
private string _reuseIdentifier;
private bool _eventRegistered;
public Action<object, EventArgs> ButtonClickedAction;
public UIButton Button { get; set; }
public ButtonCellNew(string reuseIdentifier) : base()
{
_reuseIdentifier = reuseIdentifier;
Initialize();
}
public override string ReuseIdentifier
{
get
{
return _reuseIdentifier;
}
}
private void Initialize()
{
// Cell
SelectionStyle = UITableViewCellSelectionStyle.None;
// Button
Button = new UIButton(UIButtonType.Custom);
Button.Frame = Bounds;
Button.Font = UIFont.BoldSystemFontOfSize(15);
Button.SetTitleColor(Colors.ButtonTitle, UIControlState.Normal);
Button.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
ContentView.AddSubview(Button);
}
public override void PrepareForReuse()
{
base.PrepareForReuse();
Button.TitleLabel.Text = string.Empty;
}
public void RegisterEvents()
{
ButtonClickedAction = null;
if (!_eventRegistered)
{
Button.TouchUpInside += ButtonClicked;
_eventRegistered = true;
}
}
private void ButtonClicked(object sender, EventArgs e)
{
if (ButtonClickedAction != null)
ButtonClickedAction(sender, e);
}
}
}
MyTableViewController.cs
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
else if (indexPath.Section == (int)SupportTableViewSection.Button && indexPath.Row == (int)SupportTableViewButtonRow.Close)
{
var cell = tableView.DequeueReusableCell("buttonCell") as ButtonCellNew;
if (cell == null)
cell = new ButtonCellNew("buttonCell");
cell.Button.SetTitle("Support Einstellungen schliessen", UIControlState.Normal);
cell.RegisterEvents();
cell.ButtonClickedAction = ExitSupportSettings;
return cell;
}
}
Try removing the PrepareForReuse method in your ButtonCellNew class.
I had similar issues with it on iOS 7 and I removed it completely. It seems as its behavior has somewhat changed, as it's called by the system right before the cell is returned from the DequeueReusableCell method. Apparently, the "new" behavior includes calling the method at some other point also. Or... it's a bug or something.
It's not that important anyway, as Apple only suggests using it for resetting UI-related properties and not content-related properties.
So you can live without:
Button.TitleLabel.Text = string.Empty;

Selecting all text in a UITextView on focus only after UIAlertView

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

Resources