Deleting a section from a UITableView. NSIndexSet parameter? - c#

I am trying to delete a section in a table after I have verified it has no more rows, but I am not sure what I am supposed to pass to it for the NSIndexSet parameter. Here is a code snippet I am using it in:
public override void CommitEditingStyle (UITableView tableView, UITableViewCellEditingStyle editingStyle, NSIndexPath indexPath)
{
if (editingStyle == UITableViewCellEditingStyle.Delete) {
BreakawayDB.UpdateUserTeam (_indexedTableItems[_keys[indexPath.Section]][indexPath.Row].TeamID, false);
_indexedTableItems[_keys[indexPath.Section]].RemoveAt (indexPath.Row);
tableView.DeleteRows (new NSIndexPath[] { indexPath }, UITableViewRowAnimation.Fade);
if(_indexedTableItems[_keys[indexPath.Section]].Count == 0){
tableView.DeleteSections( new NSIndexSet[] { ????? }, UITableViewRowAnimation.Fade);
}
}
}
Any tips?

try this:
tableView.DeleteSections( NSIndexSet.FromIndex (indexPath.Section), UITableViewRowAnimation.Fade);

Related

Swift extension with inheritance to c# extension methods?

I'm trying to convert a piece of Swift code to c#.
I know c# method extension but in this case the swift code inherit a class:
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return characters.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = characters[indexPath.row]
return cell
}
}
Is it possible to do this in c#?
EDIT: The code comes from here.
EDIT 2: Found the solution in the Xamarin docs.
Xamarin.iOS is based on Objective-C, which will have some difference with swift . In your case , it seems that you want to implement the DataSource of UITableView , right? If so , you could check the following code
1. Create a subclass of UITableViewSource
public class MyTableSource : UITableViewSource {
string[] characters;
string CellIdentifier = "TableCell";
public TableSource (string[] items)
{
characters = items;
}
public override nint RowsInSection (UITableView tableview, nint section)
{
return characters.Length;
}
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell (CellIdentifier);
string item = characters[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;
}
}
2 . In ViewController
var TableView = new UITableView(View.Bounds);
string[] tableItems = new string[] {"111","222","333","444","555","666"};
table.Source = new MyTableSource(tableItems);

Sorting in Tableview

I am new to xamarin.ios wants to sort tableview in alphabetical order.ie every alphabet should display all the books starting with respective letter.I am able to list the details in tableview..need to sort and update cells
public class BooklistTableSourceClass : UITableViewSource
{
public List<Booklist> Bookdata { get; set; }
BooklistViewController parentcontroller;
NSString cellIdentifier = new NSString("BooklistCell");
public BooklistTableSourceClass(List<Booklist> listdata,BooklistViewController callingcontroller)
{
this.Bookdata = listdata;
this.parentcontroller = callingcontroller;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return Bookdata.Count;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = (BooklistCell)tableView.DequeueReusableCell("Bcell_id", indexPath);
var Bookitem = Bookdata[indexPath.Row];
cell.UpdateCell(Bookitem);
return cell;
}
}
Output:
A->section header
1)A1 //book name
2)A2
3)A3
Have you tried the Enumerable.OrderBy Method in LINQ?
Sort the Bookdata first and then pass it as source of tableView instead of UpdateCell in GetCell.
public partial class ViewController : UIViewController
{
public List<Booklist> Bookdata { get; set; }
public ViewController (IntPtr handle) : base (handle)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
Bookdata = new List<Booklist>();
Bookdata.Add(new Booklist("A2"));
Bookdata.Add(new Booklist("A3"));
Bookdata.Add(new Booklist("A1"));
Bookdata.Add(new Booklist("122"));
Bookdata.Add(new Booklist("C2"));
Bookdata.Add(new Booklist("b2"));
List<Booklist> sortedList = Bookdata.OrderBy(r => r.name).ToList();
//pass the sortedList as source of tableview
//...
}
}
public class Booklist
{
public Booklist(string n){
name = n;
}
public string name;
}
If you want the A->section header, I think there is another list that hold the header data. Or you can pick the first letter of data shows in each section as text shows in section header.

Table Section URL Calling in Xamarin

I would like to display two section tableviewcontroller. I have two urls to call to get json object and tabulate them in tableviewcontroller. I could not able to figure out how to Create a single TableSource that can handle two different instances of List.
I am posting here full source code here. I will be glad if any one able to help me out in this problem, either share a link that would be useful, or share the code.
public override nint RowsInSection(UITableView tableview, nint section)
returns me an "object reference not set" error. It seems to me that once I fecth data from the first url and it tries to tabulate tableview, however, the other URL data at that time may not be ready.
namespace TPM
{
partial class IViewController : UIViewController
{
public List<HumanTask> cTasks;
public List<HumanTask> aTasks;
public InboxViewController (IntPtr handle) : base (handle)
{
this.Title = "Inside";
}
public override void ViewDidLoad()
{
base.ViewDidLoad ();
GInbox ();
CInbox ();
}
public void CInbox()
{
var client = new RestClient ("URL");
client.Authenticator = new HttpBasicAuthenticator ("admin", "admin");
var request = new RestRequest ("other part URL");
request.AddHeader ("Accept", "application/json");
request.AddHeader ("Content-Type", "application/json");
client.ExecuteAsync (request, response => {
cTasks = Newtonsoft.Json.JsonConvert.DeserializeObject<List<HTask>> (response.Content);
InvokeOnMainThread (() => {
TableView.Source= new TableSource(cTasks,this,0);
TableView.ReloadData();
});
});
}
public void GInbox()
{
var client = new RestClient ("URL");
client.Authenticator = new HttpBasicAuthenticator ("admin", "admin");
var request = new RestRequest ("the rest URL");
request.AddHeader ("Accept", "application/json");
request.AddHeader ("Content-Type", "application/json");
client.ExecuteAsync (request, response => {
aTasks = Newtonsoft.Json.JsonConvert.DeserializeObject<List<HTask>> (response.Content);
InvokeOnMainThread (() => {
TableView.Source= new TableSource(aTasks,this,1);
TableView.ReloadData();
});
});
}
public class TableSource:UITableViewSource{
List<HTask>cTableItems;
List<HTask>aTableItems;
int defi;
string cellIdentifier="TableCell";
private IViewController iv;
public TableSource (List<HTask>items, IViewController vc, int def)
{
if(def==0)
{
cTableItems=items;
}
else if(def==1)
{
aTableItems=items;
}
iv=vc;
defi=def;
}
public override nint NumberOfSections (UITableView tableView)
{
return 2;
}
public override nfloat GetHeightForHeader (UITableView tableView, nint section)
{
if(section==0){
return 40;
}
if(section == 1) {
return 40;
}
return 40;
}
public override UIView GetViewForHeader(UITableView tableView, nint section)
{
UIView headerView = new UIView(new RectangleF (0, 0, (float)UIScreen.MainScreen.Bounds.Width, (float)tableView.SectionHeaderHeight));
headerView.BackgroundColor = UIColor.Black;
UILabel sectionTitle = new UILabel( new RectangleF(10, (float)((headerView.Frame.Height - 22) / 2), 200, 24));
sectionTitle.Font = UIFont.BoldSystemFontOfSize(22);
sectionTitle.TextColor = UIColor.White;
sectionTitle.TextAlignment = UITextAlignment.Right;
if (section == 0) {
sectionTitle.Text = "Cmed";
}
else if (section == 1) {
sectionTitle.Text = "Asy";
}
headerView.AddSubview(sectionTitle);
return headerView;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
if (section == 0)
return cTableItems.Count;
else
return aTableItems.Count;
}
public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(cellIdentifier);
if (cell == null)
cell = new UITableViewCell(UITableViewCellStyle.Subtitle, cellIdentifier);
if (indexPath.Section == 0) {
cell.TextLabel.Text = cTableItems [indexPath.Row].displayName;
cell.DetailTextLabel.Lines = 3;
cell.DetailTextLabel.Text = "Process ID:" + cTableItems [indexPath.Row].processInstanceId + "\n" + DateTime.Parse (Convert.ToDateTime (cTableItems [indexPath.Row].createdOn).ToShortTimeString ());
if (cTableItems [indexPath.Row].priority == 0) {
cell.ImageView.Image = UIImage.FromFile ("Images/green.png");
}
else if (cTableItems [indexPath.Row].priority == 1) {
cell.ImageView.Image = UIImage.FromFile ("Images/yellow.png");
}
else if (cTableItems [indexPath.Row].priority == 2) {
cell.ImageView.Image = UIImage.FromFile ("Images/red.png");
}
}
else if (indexPath.Section == 1) {
cell.TextLabel.Text = assignTableItems [indexPath.Row].displayName;
cell.DetailTextLabel.Lines = 3;
cell.DetailTextLabel.Text = "Process ID:" + aTableItems [indexPath.Row].processInstanceId + "\n" + DateTime.Parse (Convert.ToDateTime (aTableItems [indexPath.Row].createdOn).ToShortTimeString ());
if (aTableItems [indexPath.Row].priority == 0) {
cell.ImageView.Image = UIImage.FromFile ("Images/green.png");
}
else if (aTableItems [indexPath.Row].priority == 1) {
cell.ImageView.Image = UIImage.FromFile ("Images/yellow.png");
}
else if (aTableItems [indexPath.Row].priority == 2) {
cell.ImageView.Image = UIImage.FromFile ("Images/red.png");
}
}
cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
return cell;
}
public override nfloat GetHeightForRow (UITableView tableView, Foundation.NSIndexPath indexPath)
{
return 60;
}
}
}
}
Based on Jason answer: I am getting the following error:
Second update based on Jason answer:
Third update based on Jason answer:
Instead of passing the two sets of data in the constructor, pass them as properties - this allows you to set them after the Source has been created, which is useful since you are getting the data asynchronously.
public class TableSource:UITableViewSource{
public List<HTask> cTableItems;
public List<HTask> aTableItems;
string cellIdentifier="TableCell";
private IViewController iv;
public TableSource (IViewController vc)
{
aTableItems = new List<HTask>();
cTableItems = new List<HTask>();
iv=vc;
}
Then create your Source once when you create the VC
public override void ViewDidLoad()
{
base.ViewDidLoad ();
TableView.Source = new TableSource(this);
GInbox ();
CInbox ();
}
Finally, when you get the data don't recreate your Source, just update it with the data: (repeat the same thing for your other dataset)
public void CInbox()
{
var client = new RestClient ("URL");
client.Authenticator = new HttpBasicAuthenticator ("admin", "admin");
var request = new RestRequest ("other part URL");
request.AddHeader ("Accept", "application/json");
request.AddHeader ("Content-Type", "application/json");
//request.Method = (string)"GET";
client.ExecuteAsync (request, response => {
cTasks = Newtonsoft.Json.JsonConvert.DeserializeObject<List<HTask>> (response.Content);
InvokeOnMainThread (() => {
((TableSource)this.TableView.Source).cTableItems = cTasks;
TableView.ReloadData();
});
});

Xamarin C# Two UITableViewCells in one UITableView

I am trying to put two different UITableViewCell's into one UITableView however when I try to load data into a TableSource It only allows me to send one List<> at a time. However I need two List<>'s for both my Cells to display. The two Lists in my TableSource.cs class are public variables called instaData and faceData. When I run Individual requests for getting instaData and faceData it works flawlessly. Better shown then explained:
Request for InstaData
var client = new RestClient ("https://api.instagram.com/v1");
client.ExecuteAsync (request, response => {
var rootObject = JsonConvert.DeserializeObject<RootObject> (response.Content);
InstagramObject.next_url = rootObject.pagination.next_url.ToString();
FLDTRequest.instagramDataCopy = rootObject.data;
table.InvokeOnMainThread (() => {
table.Source = new TableSource(stream);
((TableSource)table.Source).instaData = rootObject.data;
table.ReloadData ();
});
});
Request for FaceData
var client = new RestClient ("https://graph.facebook.com/");
client.ExecuteAsync (request, response => {
var rootObject = JsonConvert.DeserializeObject<Floadt.Core.Facebook.RootObject> (response.Content);
FLDTRequest.facebookDataCopy = rootObject.data;
table.InvokeOnMainThread (() => {
table.Source = new TableSource(stream);
((TableSource)table.Source).faceData = rootObject.data;
table.ReloadData ();
});
});
Basically I call both methods when I want to get both data but I usually get a error from the Method I call last saying that that Object is not a reference. For Example: If i call faceData request last it would say Object is not a reference. Here is my TableSource Class:
public class TableSource : UITableViewSource
{
StreamViewController controller;
public List<Datum> instaData { get; set; }
public List<string> twitData { get; set; }
public List<Floadt.Core.Facebook.Datum> faceData { get; set; }
public TableSource(StreamViewController stream)
{
controller = stream;
}
public override int RowsInSection (UITableView tableview, int section)
{
return faceData.Count;
}
public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
if (indexPath.Row % 2 == 0) {
return 340;
} else {
return 436;
//return 210;
}
}
public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
if (indexPath.Row % 2 == 0) {
NetworkCheck netCheck = new NetworkCheck ();
netCheck.runCheck ();
// bool log = netCheck.anyLoggedIn ();
if (tableView.ContentSize.Height - UIScreen.MainScreen.Bounds.Height <= tableView.ContentOffset.Y) {
BTProgressHUD.Show ("Getting more...");
FLDTRequest.getInstagramNextPage (tableView);
BTProgressHUD.Dismiss ();
}
var cell = tableView.DequeueReusableCell (InstagramCell.Key) as InstagramCell;
if (cell == null) {
cell = new InstagramCell ();
var views = NSBundle.MainBundle.LoadNib ("InstagramCell", cell, null);
cell = Runtime.GetNSObject (views.ValueAt (0)) as InstagramCell;
}
//Datum h = instaData [indexPath.Row/2];
//cell.BindData (h);
return cell;
} else {
NetworkCheck netCheck = new NetworkCheck ();
netCheck.runCheck ();
// bool log = netCheck.anyLoggedIn ();
if (tableView.ContentSize.Height - UIScreen.MainScreen.Bounds.Height <= tableView.ContentOffset.Y) {
BTProgressHUD.Show ("Getting more...");
FLDTRequest.getInstagramNextPage (tableView);
BTProgressHUD.Dismiss ();
}
var cell = tableView.DequeueReusableCell (FacebookCell.Key) as FacebookCell;
if (cell == null) {
cell = new FacebookCell ();
var views = NSBundle.MainBundle.LoadNib ("FacebookCell", cell, null);
cell = Runtime.GetNSObject (views.ValueAt (0)) as FacebookCell;
}
var fbPhotoCell = tableView.DequeueReusableCell (FacebookPhotoCell.Key) as FacebookPhotoCell;
if (fbPhotoCell == null) {
fbPhotoCell = new FacebookPhotoCell ();
var views = NSBundle.MainBundle.LoadNib ("FacebookPhotoCell", cell, null);
fbPhotoCell = Runtime.GetNSObject (views.ValueAt (0)) as FacebookPhotoCell;
}
Floadt.Core.Facebook.Datum f = faceData [indexPath.Row/2];
fbPhotoCell.BindData (f);
return fbPhotoCell;
}
}
}
It looks like you are trying to set table.Source twice, once for each List? You need to merge your lists into a single data source, and create a UITableViewCell that can visualize both data types.
1)Drag and Drop UITableView to ViewController and add constraints.
2)Add two Prototype cells and Associate with Two UITableViewCells.
3) Set up UITableViewSource(Combines UITableVIewDataSource and UITableViewDelegate).
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
this.sampleTableView.Source = new SampleTableViewSource ();
}
Add Source class to ViewController.
//Table Source
public class SampleTableViewSource : UITableViewSource
{
string CellIdentifier = "sampleTableViewCellID";
string CellIdentifier2 = "sampleTableViewCell2ID";
public override nint RowsInSection(UITableView tableview, nint section)
{
return 2;
}
public override nint NumberOfSections (UITableView tableView)
{
return 1;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = new UITableViewCell ();
//---- if there are no cells to reuse, create a new one
if (indexPath.Row == 0)
{
cell = tableView.DequeueReusableCell (CellIdentifier) as SampleTableViewCell;
}
else if(indexPath.Row == 1 ) {
cell = tableView.DequeueReusableCell (CellIdentifier2) as sampleTableViewCell2;
}
return cell;
}
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
tableView.DeselectRow (indexPath, true);
}
}

Why does my UIPickerView crashing when selecting

I have created a sample on github Github link
When clicking on a row or trying to scroll in the UIPickerView it will crash and i wonder why.
// create a ActionSheet
var actionPickerSheet = new UIActionSheet("Select a Category");
actionPickerSheet.Style = UIActionSheetStyle.BlackTranslucent;
// Create UIpickerView
var catPicker = new UIPickerView(){
Model = new catPickerModel(),
AutosizesSubviews = true,
Hidden = false,
ShowSelectionIndicator = true
};
// show inside view and add the catPicker as subView
actionPickerSheet.ShowInView(View);
actionPickerSheet.AddSubview(catPicker);
// resize both views so it fits smoothly
actionPickerSheet.Frame = new RectangleF(0,100,320,500);
catPicker.Frame = new RectangleF(actionPickerSheet.Frame.X,actionPickerSheet.Frame.Y-25,actionPickerSheet.Frame.Width, 216);
And the Model
private class catPickerModel : UIPickerViewModel
{
public string[] protocolNames = new string[]
{
"Web", "Phone Call", "Google Maps", "SMS", "Email"
};
public override int GetComponentCount(UIPickerView uipv)
{
return 1;
}
public override int GetRowsInComponent( UIPickerView uipv, int comp)
{
//each component has its own count.
int rows = protocolNames.Length;
return(rows);
}
public override string GetTitle(UIPickerView uipv, int row, int comp)
{
//each component would get its own title.
return protocolNames[row];
}
public override void Selected(UIPickerView uipv, int row, int comp)
{
Console.WriteLine("selected:" + row);
}
public override float GetComponentWidth(UIPickerView uipv, int comp)
{
return 300f;
}
}
I have no idea why it keeps crashing, is it some method i am missing in the Model or am i trying to do this in the wrong way ?
Thanks
Try to make your catPicker to a private variable of the class:
namespace TextfieldUIPickerView
{
public partial class TextfieldUIPickerViewViewController : UIViewController
{
private UIPickerView catPicker;
...
Looks like the GC has collected your catPicker and disposed it.

Categories

Resources