Single selection for every UITableViewSection iOS Xamarin - ios

I have a UITableView with 2-3 sections. I want to implement a functionality where single row from every section can be selected.
Something like so :-
I have tried enabling multiple selection on the UITableView. But it allows me to select multiple rows from all the sections. I want to select only one row at a time from every section.
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.CellAt(indexPath);
if (cell.Accessory == UITableViewCellAccessory.None)
{
cell.Accessory = UITableViewCellAccessory.Checkmark;
}
else
{
cell.Accessory = UITableViewCellAccessory.None;
}
selectedSection = indexPath.Section;
}
public override void RowDeselected(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.CellAt(indexPath);
cell.Accessory = UITableViewCellAccessory.None;
}

You can use a list to store flags for every section which you selected last time.
List<NSIndexPath> selectList = new List<NSIndexPath>();
for(int i = 0; i < tableviewDatasource.Count; i++)
{
//initial index 0 for every section
selectList.Add(NSIndexPath.FromRowSection(0, i));
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
//anti-highlight last cell
NSIndexPath lastindex = selectList[indexPath.Section];
var lastcell = tableView.CellAt(lastindex);
lastcell.Accessory = UITableViewCellAccessory.None;
//highlight selected cell
var cell = tableView.CellAt(indexPath);
cell.Accessory = UITableViewCellAccessory.Checkmark;
//update the selected index
selectList.RemoveAt(indexPath.Section);
selectList.Insert(indexPath.Section, indexPath);
}

Related

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

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.

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

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

TextField Change event in a CustomCell

I have been working on CustomCell in Xamarin.iOS platform. The following code is working fine. I have tableItems which is List that stores Start and End values.
And I also have a class(SettingCustomCell) where I have programmatically created TextFields to display Start and End values.
I wonder how could I detect/capture when user changes either Start or End values in the TextField in my current implementation.
MainTableViewController
tableItems.Add (new TableItem() {Start=1000, End=4000});
tableItems.Add (new TableItem() {Start=4000, End=6000});
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
SettingsCustomCell cell = tableView.DequeueReusableCell (cellIdentifier) as SettingsCustomCell;
if (cell == null) {
cell = new SettingsCustomCell (cellIdentifier);
}
cell.UpdateCell (tableItems [indexPath.Row].Start, tableItems [indexPath.Row].End);
return cell;
}
SettingsCustomCell
public CustomCell (NSString cellId) : base (UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.None;
firstLabel = new UITextField ();
secondLabel = new UITextField ();
ContentView.Add (firstLabel);
ContentView.Add (secondLabel);
}
public void UpdateCell (int caption, int subtitle)
{
firstLabel.Text = caption.ToString();
secondLabel.Text = subtitle.ToString();
}
Create the eventhandler in the tablecell. And when the your UITextField text change call this eventhandler.
public EventHandler<bool> EditingChanged;
//some code here
firstTextField.ValueChanged += (s, e) => {
if(EditingChanged!=null)
EditingChanged(this,true);
}
Than in your DataSource you subscribe for EditingChanged event and create another eventhandler which will be called when the EditingChanged will be executed.
public EventHandler<bool> SourceEditingChanged;
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
SettingsCustomCell cell = tableView.DequeueReusableCell (cellIdentifier) as SettingsCustomCell;
if (cell == null) {
cell = new SettingsCustomCell (cellIdentifier);
}
cell.UpdateCell (tableItems [indexPath.Row].Start, tableItems [indexPath.Row].End);
cell.EditingChanged += {
if(SourceEditingChanged!=null)
SourceEditingChanged(this,true);
};
return cell;
}
Subscribe for your SourceEditingChange Event from viewController.
MySource.SourceEditingChange += (s,e) =>{
//Your Code here
}

Editable UITableViewCell - EditingStyleForRow() not invoked

I am trying to implement deletable UITableViewCells. My UITableView has 3 sections. The 1st section contains one cell for every element of a List (called items for simplicity). Various elements (UILabels and a UIButton) are added to each cell.
Like most articles on the web, my code implements the delegate methods that are in charge of making cells editable:
public override bool CanEditRow(UITableView tableView, NSIndexPath indexPath) {
if (indexPath.Section == 0 && items.Count > 0) {
return true;
}
return false;
}
public override UITableViewCellEditingStyle EditingStyleForRow(UITableView tableView, NSIndexPath indexPath) {
if (indexPath.Section == 0 && items.Count > 0) {
return UITableViewCellEditingStyle.Delete;
}
return UITableViewCellEditingStyle.None;
}
public override void CommitEditingStyle(UITableView tableView, UITableViewCellEditingStyle editingStyle, NSIndexPath indexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
items.RemoveAt(indexPath.Row);
tableView.DeleteRows(new NSIndexPath[] { indexPath }, UITableViewRowAnimation.None);
}
}
Whether or not a cell is editable/deletable is decided in GetCell():
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) {
string cellIdentifier;
UITableViewCell cell;
if (indexPath.Section == 0) {
if (items.Count == 0) {
// Generate a "No data here..." cell
...
} else {
cellIdentifier = "ItemCell";
cell = tableView.DequeueReusableCell(cellIdentifier);
if (cell == null) {
// Create a new cell
...
}
cell.Editing = true; // Make the cell deletable
cell.ShouldIndentWhileEditing = true;
cell.ShowingDeleteConfirmation = true;
// Assign item values to the cell
...
}
} else if (...) { // Other sections go here
}
return cell;
}
Placing Console.Writes and breakpoints all over the place made me believe that the EditingStyleForRow() delegate method is not even invoked. None of it's Console.Writes showed up, no breakpoint in there was ever reached.
All the other delegates work fine though. Table contents show up as expected, just not editable/deletable.
Any hints on what I am doing wrong? Thanks in advance.
EDIT:
Apple docs say that UITableViewCellEditingStyle.Delete will be set for editable cells if the delegate method is not implemented. But it doesn't work without the method either.
EDIT 2:
Thanks to Ratinhos hint, EditingStyleForRow() is now invoked and correctly returns UITableViewCellEditingStyle.Delete, but the delete controls still don't appear.
did you invoke:
[tableView setEditing:animated:]
?
It works now. I completely removed those:
cell.Editing = true; // Make the cell deletable
cell.ShouldIndentWhileEditing = true;
cell.ShowingDeleteConfirmation = true;
Also, CanEditRow() doesn't really seem to be required. All that is left is tableView.Editing = true and the implementations of EditingStyleForRow() and CommitEditingStyle().

Resources