How to read cell value long press gesture on table cell in xamarin.ios? - uitableview

I have Tableview with longpress cell.
I can't read the data inside the cell which have been long pressed.
rowselected() method is not the right way because I must select cell first. I didn't want to select cell first.
This is my table adapter class:
internal class AbsetAdapterClass : UITableViewSource
{
private List<benood2.AbsentClass> absentList;
public AbsetAdapterClass(List<benood2.AbsentClass> absentList)
{
this.absentList = absentList;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = (TableClass)tableView.DequeueReusableCell("cell_id", indexPath);
var AbsentDay = absentList[indexPath.Row];
var longPressGesture = new UILongPressGestureRecognizer(LongPressMethod);
cell.AddGestureRecognizer(longPressGesture);
cell.UpdateCell(AbsentDay);
return cell;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return absentList.Count;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
PublicClass.ReadCellValue = "";
var GetCellValue = absentList[indexPath.Row].BandValue;
tableView.DeselectRow(indexPath, true);
}
void LongPressMethod(UILongPressGestureRecognizer gestureRecognizer)
{
if (gestureRecognizer.State == UIGestureRecognizerState.Began)
{
Toast.MakeToast("I want to read the cell data ").SetTitle(PublicClass.ReadCellID.ToString()).SetDuration(ToastDuration.Regular).Show();
}
}
}
I can't get the long press cell data

You could attach LongPressGesture to the UITableView instead of the UITableViewCell.
You could try the following code (Note: i made my demo based on the Xamarin.iOS official samples):
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
table = new UITableView(new CGRect(0, 0, width, height));
...
// add longPressGesture to the tableView
var longPressGesture = new UILongPressGestureRecognizer(LongPressMethod);
table.AddGestureRecognizer(longPressGesture);
...
}
Then for LongPressMethod:
void LongPressMethod(UILongPressGestureRecognizer gestureRecognizer)
{
var p = gestureRecognizer.LocationInView(table);
var indexPath = table.IndexPathForRowAtPoint(p);
if (indexPath == null)
{
Console.WriteLine("Long press on table view but not on a row.");
}
else if (gestureRecognizer.State == UIGestureRecognizerState.Began)
{
Console.WriteLine("Long press on {0} row", indexPath.Row);
//you could get the selectedItem through the Row index
}
}
For more info, you could refer to Working with Tables and Cells in Xamarin.iOS.
Hope it works for you.

Related

Swipe to delete cell Height is decrease every time in xamarin ios

I am new to iOS. I am creating TableView with swipe to delete the cell. But When I swipe every time the cell height is decrease. I am using iOS 10. The below code I have used.
Code :
class AppointmentSourceClass : UITableViewSource
{
List<AppointmentItem> appointments;
public AppointmentSourceClass(List<AppointmentItem> appointments)
{
this.appointments = appointments;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
ApointListCell cell = tableView.DequeueReusableCell(ApointListCell.Key) as ApointListCell ?? ApointListCell.Create();
var item = appointments[indexPath.Row];
cell.BindData(item);
cell.Layer.MasksToBounds = false;
cell.Layer.CornerRadius = 5.0f;
cell.BackgroundColor = UIColor.White;
cell.SelectionStyle = UITableViewCellSelectionStyle.None;
return cell;
}
public override void CommitEditingStyle(UITableView tableView, UITableViewCellEditingStyle editingStyle, NSIndexPath indexPath)
{
switch (editingStyle)
{
case UITableViewCellEditingStyle.Delete:
appointments.RemoveAt(indexPath.Row);
tableView.DeleteRows(new NSIndexPath[] { indexPath},UITableViewRowAnimation.Fade);
break;
case UITableViewCellEditingStyle.None:
break;
}
}
public override bool CanEditRow(UITableView tableView, NSIndexPath indexPath)
{
return true;
}
public override string TitleForDeleteConfirmation(UITableView tableView, NSIndexPath indexPath)
{
return "Trash ( ";
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return appointments.Count;
}
}
}
Output :
Before Swipe Image :
After Swipe Image :
Found the solution.
In the TableCell I have use below code to seperate the two tableCell and make space between them. If i remove the code then it working fine.
public override CoreGraphics.CGRect Frame
{
get
{
return base.Frame;
}
set
{
value.Y += 4;
value.Height -= 2 * 4;
base.Frame = value;
}
}

Update textfield after a row is selected in tableview Xamarin.IOS

Here is a scenario that I am encountering. I am having a login screen with UserName as one of the fields. The user can select a user using a dropdown list (implemented via a button - to simulate drop down arrow, a popover controller and a table view). I having a controller (UserNameController) which has the logic of fetching the usernames and binding the same to the table view within it. The UserNameController is called via ViewController.cs which has the textfield and the dropdown button using below code:
var content = this.Storyboard.InstantiateViewController("UserNameLookUp") as UserNameController;
UIPopoverController popover = new UIPopoverController(content);
//popover.SetPopoverContentSize(new SizeF(80, 80), true);
popover.PresentFromRect(new RectangleF(float.Parse((sender.Frame.X + 115).ToString()),
float.Parse((sender.Frame.Y + 180).ToString())
, 80, 80), View, UIPopoverArrowDirection.Up, true);
and in UserNameController:
public override void ViewDidLoad()
{
string[] userName = new string[10];
tblVwUserName.Source = new TableSource(userName);
}
}
and TabelSource.cs looks like this:
public class TableSource : UITableViewSource
{
string[] TableItems;
string CellIdentifier = "TableCell";
public TableSource(string[] items)
{
TableItems = items;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return TableItems.Length;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(CellIdentifier);
string item = TableItems[indexPath.Row];
//---- if there are no cells to reuse, create a new one
if (cell == null)
{ cell = new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier); }
cell.TextLabel.Text = item;
return cell;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
// HOW TO SET BACK THE USERNAME TEXT FIELD IN VIEWCONTROLLER? AND CLOSE THE POPUP
tableView.DeselectRow(indexPath, true);
}
}
Now how do i need to display the selected username in the viewcontroller's textfield and close the popup?
Thanks!
Sid
I typically solve this requirement with properties on the TableViewSource and the TableViewController. Your source will change to:
public class TableSource : UITableViewSource
{
string[] TableItems;
string CellIdentifier = "TableCell";
public string SelectedItem {get; set;}
public TableSource(string[] items)
{
TableItems = items;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return TableItems.Length;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(CellIdentifier);
string item = TableItems[indexPath.Row];
//---- if there are no cells to reuse, create a new one
if (cell == null)
{ cell = new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier); }
cell.TextLabel.Text = item;
return cell;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
SelectedItem = items[indexPath.Row];
tableView.DeselectRow(indexPath, true);
}
}
Now you need a way to get that value. There are two possible ways:
1) UserNameController is of type UITableViewController, than it would be (content.TableView.Source as TableSource).SelectedItem
2) UserNameController is not of type UITableViewController, than I would add a property too that returns the property of the TableViewSource.
Last thing to do is closing the Popover and query the selected item. For this task I would wrap the UserNameController in a UINavigationController and add a Cancel and a Done button into it like this:
var navigationController = new UINavigationController(content);
var popover = new UIPopoverController(navigationController);
content.NavigationItem.SetLeftBarButtonItem(new UIBarButtonItem(UIBarButtonSystemItem.Cancel, (s, e) =>
{
parentController.DismissViewController(true, null);
}), true);
content.NavigationItem.SetRightBarButtonItem(new UIBarButtonItem(UIBarButtonSystemItem.Done, (s, e) =>
{
parentController.DismissViewController(true, null);
var selectedItem = (content.Source as TableSource).SelectedItem;
}), true);

How do I put a button inside a tableview cell?

I'm new to this, so I have troubles doing that. My goal is too put, like the title said, a button inside a cell. If you want to see my code, so that this could help you to answer this question, here is the code:
using System;
using System.Collections.Generic;
using System.Text;
using Foundation;
using UIKit;
namespace TableView
{
public class TableSource : UITableViewSource
{
string[] tableItems;
string cellIdentifier = "TableCell";
public TableSource (string[] items)
{
tableItems = items;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return tableItems.Length;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
new UIAlertView("Alert", "You selected: " + tableItems[indexPath.Row], null, "Next Site", null).Show();
tableView.DeselectRow(indexPath, true);
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(cellIdentifier);
if (cell == null)
cell = new UITableViewCell(UITableViewCellStyle.Subtitle, cellIdentifier);
cell.TextLabel.Text = tableItems[indexPath.Row];
if(indexPath.Row > -1)
cell.DetailTextLabel.Text = tableItems[indexPath.Row - 0];
return cell;
}
}
}
Here is the code for ViewController, if this is needed to.
Create a custom TableViewCell and add the button there. Than use that custom TableViewCell in your GetCell method.
class MyButtonTableViewCell : UITableViewCell
{
public UIButton MyButton { get; private set; }
public MyButtonTableViewCell() : base(UITableViewCellStyle.Default, "MyButtonCell")
{
MyButton = new UIButton(UIButtonType.System);
MyButton.Frame = ContentView.Bounds;
MyButton.SetTitle("My Title", UIControlState.Normal);
ContentView.AddSubview(MyButton);
}
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell("MyButtonCell");
if (cell == null)
cell = MyButtonTableViewCell();
return cell;
}
First of all you need to add a tag to the button so that you can see what button is being pressed inside the cellForRowAtIndexPath function like this:
cell.Button.tag = indexPath.row
Then inside an IBAction you can see exactly what row's button was pressed like this:
#IBAction func buttonPressed(sender: AnyObject)
{
let button = sender as! UIButton
let index = NSIndexPath(forRow: button.tag, inSection: 0)
}

How to insert row at desired index in UITableView Xamarin.ios?

i want to add a couple of rows on the index next to the selected row index.
For example if i have clicked row at index 4 i want some rows to added at index 5,6,7. and the actual rows of these indexes shift forward on 8,9,10 etc.
In your table view source MyTableViewSource you have to override RowSelected. In this method, you check your row number and add items to you table view source's Items after adding them, you have to call ReloadData().
class MyTableViewSource : UITableViewSource
{
private readonly UITableView _table;
public List<string> Items { get; }
public MyTableViewSource(UITableView table)
{
_table = table;
Items = new List<string> { "Hello", "World", "Bla", "Foo" };
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var item = Items[indexPath.Row];
var cell = // create cellfor item
return cell;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return Items.Count;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
if (indexPath.Row == 2)
{
Items.Insert(3, "Horst");
Items.Insert(4, "Klaus");
Items.Insert(5, "Peter");
_table.ReloadData();
}
}
}
Creating them:
var table = new UITableView();
table.Source = new MyTableViewSource(table);
If you want more control over the animation, you can use this version:
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
if (indexPath.Row == 2)
{
_table.BeginUpdates();
Items.Insert(3, "Horst");
Items.Insert(4, "Klaus");
Items.Insert(5, "Peter");
_table.InsertRows(new[] { NSIndexPath.Create(0, 3), NSIndexPath.Create(0, 4), NSIndexPath.Create(0, 5) }, UITableViewRowAnimation.Left);
_table.EndUpdates();
}
}

Multiple tabs in rootview

I am very new to XCode and Monotouch development. I am trying to add multiple tabs in root view (Master-Detail application). I am using Mono for development and xCode 4 for UI design. For example, one tab shows list of employees and another tab shows list of departments.
I removed the default table view in the rootviewController.xib file and replaced with tabbedview but I cant get new table view for each tab working.
I would appreciate if anyone can show me the correct way of doing this.
UPDATED: I use the code below to add 2 tabs and 2 table view. One is to hold "Securities" and the other one to hold the "Indicators"
using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Collections.Generic;
namespace ChartQ
{
public partial class RootViewController : UITabBarController
{
public DetailViewController DetailVC { get; set; }
private List<SecurityInfo> listSecInfo = new List<SecurityInfo>();
private List<Indicator> listIndicator = new List<Indicator>();
public RootViewController () : base ("RootViewController", null)
{
this.Title = NSBundle.MainBundle.LocalizedString ("Securities", "Securities");
//this.ClearsSelectionOnViewWillAppear = false;
this.ContentSizeForViewInPopover = new SizeF (100f, 200f);
//this.ContentSizeForViewInPopover = new SizeF (320f, 600f);
// Custom initialization
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
//Read data from Database..
UITableViewController secController = new UITableViewController();
UITableViewController IndiController = new UITableViewController();
this.AddChildViewController(secController);
this.AddChildViewController(IndiController);
SQLLiteDatabase db = new SQLLiteDatabase();
listSecInfo = db.ReadSecurities();
listIndicator = db.ReadIndicator();
//TableView.Source = new SecuritiesDataSource (this);
secController.TableView.Source = new SecuritiesDataSource (this);
secController.TableView.SelectRow (NSIndexPath.FromRowSection (0, 0), false, UITableViewScrollPosition.Middle);
IndiController.TableView.Source = new IndicatorDataSource (this);
IndiController.TableView.SelectRow (NSIndexPath.FromRowSection (0, 0), false, UITableViewScrollPosition.Middle);
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
// Return true for supported orientations
return true;
}
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 ViewDidUnload ()
{
base.ViewDidUnload ();
// Clear any references to subviews of the main view in order to
// allow the Garbage Collector to collect them sooner.
//
// e.g. myOutlet.Dispose (); myOutlet = null;
ReleaseDesignerOutlets ();
}
class SecuritiesDataSource : UITableViewSource
{
static NSString cellIdentifier = new NSString ("CellId");
RootViewController controller;
public SecuritiesDataSource (RootViewController controller)
{
this.controller = controller;
}
// 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 controller.listSecInfo.Count;
}
public override string TitleForHeader (UITableView tableView, int section)
{
return "Securities";
}
// Customize the appearance of table view cells.
public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
string cellIdentifier = "Cell";
var cell = tableView.DequeueReusableCell (cellIdentifier);
if (cell == null) {
cell = new UITableViewCell (UITableViewCellStyle.Subtitle, cellIdentifier);
//Add in a detail disclosure icon to each cell
cell.Accessory = UITableViewCellAccessory.DetailDisclosureButton;
}
// Configure the cell.
var sInfo = controller.listSecInfo [indexPath.Row];
cell.TextLabel.Text = String.Format ("{0}",sInfo.SecCode);
cell.DetailTextLabel.Text = sInfo.SecName;
return cell;
}
private void InfoAlert (string msg)
{
using (UIAlertView av = new UIAlertView("Info", msg, null, "OK", null)) {
av.Show ();
}
}
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
var sInfo = controller.listSecInfo [indexPath.Row];
controller.DetailVC.DrawChart(sInfo.SecID, sInfo.SecCode);
}
}
class IndicatorDataSource : UITableViewSource
{
static NSString cellIdentifier = new NSString ("CellId");
RootViewController controller;
public IndicatorDataSource (RootViewController controller)
{
this.controller = controller;
}
// 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 controller.listIndicator.Count;
}
public override string TitleForHeader (UITableView tableView, int section)
{
return "Indicators";
}
// Customize the appearance of table view cells.
public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
string cellIdentifier = "Cell";
var cell = tableView.DequeueReusableCell (cellIdentifier);
if (cell == null) {
cell = new UITableViewCell (UITableViewCellStyle.Subtitle, cellIdentifier);
//Add in a detail disclosure icon to each cell
cell.Accessory = UITableViewCellAccessory.DetailDisclosureButton;
}
// Configure the cell.
var sInfo = controller.listIndicator [indexPath.Row];
cell.TextLabel.Text = String.Format ("{0}",sInfo.DescriptiveName);
cell.DetailTextLabel.Text = sInfo.ShortName;
return cell;
}
private void InfoAlert (string msg)
{
using (UIAlertView av = new UIAlertView("Info", msg, null, "OK", null)) {
av.Show ();
}
}
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
var sInfo = controller.listIndicator [indexPath.Row];
//controller.DetailVC.DrawChart(sInfo.SecID, sInfo.SecCode);
}
}
}
However, it crashes when I click the second tab. I am getting the error as below
"Got a SIGSEGV while executing native code"
The first list populated ok.
I think the UITableViewController objects are getting collected and causing your abort. Make secController and secController member variables.
public partial class RootViewController : UITabBarController
{
UITableViewController secController;
UITableViewController IndiController;
public DetailViewController DetailVC { get; set; }
...
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
//Read data from Database..
secController = new UITableViewController ();
IndiController = new UITableViewController ();

Resources