I have a memory leaks issue.
I basically have a MvxTableViewController databound to a observablecollection. I create a MvxTableViewController and add it to my Controller as a child and I add the view as a subviews.
Problem is, the Cell in the table never gets disposed, leaking memory.
// When the view gets removed from the stack, the cells disposed method is never called and I can see the memory not going away, using the Xcode Instruments tool. The table dispose gets called as expected. but not the cell
public partial class ParticipantTableViewCell : MvxTableViewCell
{
readonly UILabel _nameLabel = new UILabel();
readonly UILabel _locationLabel = new UILabel();
readonly PictureContainer _pictureView = new PictureContainer(7.0f);
public ParticipantTableViewCell (IntPtr handle) : base(handle)
{
BackgroundColor = UIColor.Clear;
SelectionStyle = UITableViewCellSelectionStyle.None;
ContentView.AddSubviews(new UIView[] {_nameLabel, _locationLabel, _pictureView});
_pictureView.TransparentBackground = true;
SetupConstraints();
// Since this view is readonly, I've removed the actual binding code
// and instead manually init each views.
this.DelayBind(() => {
_nameLabel.Text = ((ParticipantViewModel)DataContext).Name;
_locationLabel.Text = ((ParticipantViewModel)DataContext).Location;
IsSelected = ((ParticipantViewModel)DataContext).IsSelected;
_pictureView.AvatarImage.Image = UIImage.FromFile ("Media/" + ((ParticipantViewModel)DataContext).AvatarUrl);
});
}
void SetupConstraints ()
{
ContentView.Subviews.ForEach(v => v.TranslatesAutoresizingMaskIntoConstraints = false);
ContentView.AddConstraints(
_pictureView.Height().EqualTo().HeightOf(ContentView),
_pictureView.Width().EqualTo().HeightOf(ContentView),
_pictureView.WithSameCenterY(ContentView),
_pictureView.Left().EqualTo(6.0f).LeftOf(ContentView),
_nameLabel.Left().EqualTo(10.0f).RightOf(_pictureView),
_nameLabel.Right().EqualTo().RightOf(ContentView),
_nameLabel.Bottom().EqualTo(2.0f).CenterYOf(ContentView),
_locationLabel.Left().EqualTo(10.0f).RightOf(_pictureView),
_locationLabel.Right().EqualTo().RightOf(ContentView),
_locationLabel.Top().EqualTo(4.0f).CenterYOf(ContentView)
);
}
// never called
protected override void Dispose (bool disposing)
{
base.Dispose(disposing);
}
}
class FriendsView : MvxTableViewController
{
protected new FriendsViewModel ViewModel { get { return (FriendsViewModel) base.ViewModel; } }
public FriendsView ()
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad();
TableView.BackgroundColor = UIColor.Clear;
TableView.SeparatorStyle = UITableViewCellSeparatorStyle.None;
TableView.RowHeight = 60;
TableView.ScrollEnabled = false;
var source = new MvxSimpleTableViewSource(TableView, typeof(ParticipantTableViewCell));
TableView.Source = source;
var set = this.CreateBindingSet<FriendsView, FriendsViewModel>();
set.Bind(source).To(vm => vm.YuFitFriends);
set.Apply();
}
}
Anybody got an idea as to why my cells are leaking ?
thanks
pat
**// never called**
protected override void Dispose (bool disposing)
{
base.Dispose(disposing);
}
Do you expect this will be called magically? NO!
Dispose is just a another method in your class which you should call when you don't want its instance anymore.
And also, you should dispose all the disposable instances in your class (eg: PictureContainer) in this Dispose method. Also, make sure you unsubscribe from any event subscriptions. Just calling base.Dispose doesn't release any reference in this class.
I got a working solution... The bugs seems to be with how MvvmCross register cells for reuse. If I derive my own class from MvxBaseTableSource instead of using MvxSimpleTableSource and I create the cells differently, I get everything to dispose properly:
class MySource : MvxTableViewSource
{
public MySource (UITableView tableView) : base(tableView)
{
}
protected override UITableViewCell GetOrCreateCellFor (UITableView tableView, NSIndexPath indexPath, object item)
{
var cell = tableView.DequeueReusableCell (ParticipantTableViewCell.Key) as ParticipantTableViewCell;
if (cell == null)
cell = new ParticipantTableViewCell ();
return cell;
}
}
and in my tableviewcontroller, I use MySource
var source = new MySource(TableView);
Now everything gets collected fine!
Related
I'm trying to create my first iOS project. I have quite well experiences with C#. I receive data with categories and articles. But I don't know, how many subcategories I will get, before the articles will be listed. The browsing though the subcategories should be done via TableView. When a User clicks a category, the subcategories (level 1) should be displayed in a tableView. Then, after touching a subcategory, the subcategories (level 2) of present should be displayed (and so on). Lastly, when there are no further subcategories, the article-list should be displayed. After touching one article, a new ViewController with the article-data should be displayed.
My question is, how to handle the navigation through the subcategories and creating segues or sth. like that. I know, that I can't use storyboard for this, because I don't know the number of subcategories and they also differ.
How can I achieve this dynamic navigation? Can you give me an example? I know how to populate data to the tableView. Only the dynamic navigation is the problem.
I now have a solution. Can someone please check, if I am doing it correctly not that I don't violate programming patterns or guidelines.
In short: In TableSource-Class I access the Storyboard and dynamically create and show the same Controller which actually is presented. But before presenting the new one, I declare an other source-class. So the TableView is used for displaying Addressbooks and Addresscards, the UIViewController is used for displaying the carddata. These two controllers are connected via segue.
Here are my Controller and both Source-Classes:
AddressbooksController.cs
public AddressbooksController (IntPtr handle) : base (handle)
{
displayModel = "addressbooks";
}
private void loadAddressbooks()
{
var AppDelegate = UIApplication.SharedApplication.Delegate as AppDelegate;
addressbooks = AppDelegate.api.DeserializeEntities<YAddressbook>(Task.Run(async () => await AppDelegate.api.Get("Yaddressbooks")).Result);
}
public void loadAddresscards()
{
var AppDelegate = UIApplication.SharedApplication.Delegate as AppDelegate;
addresscards = AppDelegate.api.DeserializeEntities<Ycard>(Task.Run(async () => await AppDelegate.api.Get("Ycards")).Result);
}
public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender)
{
base.PrepareForSegue(segue, sender);
// do first a control on the Identifier for your segu
if (segue.Identifier.Equals("segueShowAddress"))
{
var viewController = (AddresscardController)segue.DestinationViewController;
viewController.card = Card2Display;
}
}
public override void ViewDidLoad()
{
if (displayModel == "addressbooks")
{
loadAddressbooks();
tableView.Source = new AddressbooksTableSource(addressbooks.data, this);
this.NavigationController.Title = "Addressbücher";
}
else if (displayModel == "addresscards")
{
loadAddresscards();
tableView.Source = new AddresscardsTableSource(addresscards.data, this);
this.NavigationController.
}
base.ViewDidLoad();
}
AddressbooksTableSource
public class AddressbooksTableSource: UITableViewSource
{
private List<YAddressbook> addressbooks;
private string cellIdentifier = "AddressbooksCell";
private UINavigationController navigationController;
public AddressbooksTableSource(List<YAddressbook> books, AddressbooksController ab)
{
addressbooks = books;
this.navigationController = ab.ParentViewController as UINavigationController;
Console.WriteLine(ab.displayModel);
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
Console.WriteLine("Row selected" + addressbooks[indexPath.Row].displayname);
UIStoryboard Storyboard = UIStoryboard.FromName("Main", null);
AddressbooksController newab = Storyboard.InstantiateViewController("AddressbooksViewController") as AddressbooksController;
newab.displayModel = "addresscards";
navigationController.PushViewController(newab, true);
tableView.DeselectRow(indexPath, true);
}
....
}
AddresscardsTableSource
public class AddresscardsTableSource: UITableViewSource
{
private List<Ycard> addresscards;
UINavigationController navigationController;
AddressbooksController ab;
string cellIdentifier = "AddresscardCell";
public AddresscardsTableSource(List<Ycard> cards, AddressbooksController vc)
{
addresscards = cards;
navigationController = vc.ParentViewController as UINavigationController;
ab = vc;
//navigationController = tableview;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
Console.WriteLine("Row selected" + addresscards[indexPath.Row].carddata);
//UIStoryboard Storyboard = UIStoryboard.FromName("Main", null);
ab.Card2Display = addresscards[indexPath.Row];
ab.PerformSegue("segueShowAddress", indexPath);
//AddresscardController ab = Storyboard.InstantiateViewController("AddresscardViewController") as AddressbooksController;
//ab.TableView.Source = this;
//navigationController.PushViewController(ab, true);
tableView.DeselectRow(indexPath, true);
}
.....
}
It works. But am I doing it correctly? Thanks
I have created a custom NSView that i would like to place over the top of the content of a window to block any interaction while all the content is loading. The problem i was having is that i could click through the NSView to the controls below though that has now been fixed. The new problem is that even though i cannot click on the controls, when i move the mouse over text controls, the mouse switches to the I Beam icon.
How do i make the NSView completely block all interaction with everything below it?
The NSView i created is below:
[Register("StupidView")]
public class StupidView : NSView
{
public StupidView()
{
// Init
Initialize();
}
public StupidView(IntPtr handle) : base (handle)
{
// Init
Initialize();
}
[Export("initWithFrame:")]
public StupidView(CGRect frameRect) : base(frameRect) {
// Init
Initialize();
}
private void Initialize()
{
this.AcceptsTouchEvents = true;
this.WantsLayer = true;
this.LayerContentsRedrawPolicy = NSViewLayerContentsRedrawPolicy.OnSetNeedsDisplay;
}
public override void DrawRect(CGRect dirtyRect)
{
var ctx = NSGraphicsContext.CurrentContext.GraphicsPort;
ctx.SetFillColor(new CGColor(128, 128, 128, 0.7f));
ctx.FillRect(dirtyRect);
}
public override void MouseDown(NSEvent theEvent)
{
if (Hidden)
{
base.MouseDown(theEvent);
}
}
public override void MouseDragged(NSEvent theEvent)
{
if (Hidden)
{
base.MouseDragged(theEvent);
}
}
public override bool AcceptsFirstResponder()
{
return !this.Hidden;
}
public override bool AcceptsFirstMouse(NSEvent theEvent)
{
return !this.Hidden;
}
public override NSView HitTest(CGPoint aPoint)
{
return Hidden ? null : this;
}
}
I had the same problem a few weeks ago, and here is how I could manage this :
First, to prevent user interactions on the superview placed below, I added a transparent button which was there only to catch the mouse click and, if you don't have to do anything, do nothing :
private void Initialize()
{
this.AcceptsTouchEvents = true;
this.WantsLayer = true;
this.LayerContentsRedrawPolicy = NSViewLayerContentsRedrawPolicy.OnSetNeedsDisplay;
//Add button to prevent user interactions
NSButton buttonToPreventUserInteraction = new NSButton();
buttonToPreventUserInteraction.Bordered = false;
buttonToPreventUserInteraction.Transparent = true;
buttonToPreventUserInteraction.TranslatesAutoresizingMaskIntoConstraints = false;
AddSubview(buttonToPreventUserInteraction);
//If you want to add some constraints on the button, for it to resize and keep the same size of your subview
var dicoViews = new NSMutableDictionary();
dicoViews.Add((NSString)"buttonToPreventUserInteraction", buttonToPreventUserInteraction);
NSLayoutConstraint[] buttonToPreventUserInteractionHorizontalConstraints = NSLayoutConstraint.FromVisualFormat("H:|[buttonToPreventUserInteraction]|", NSLayoutFormatOptions.DirectionLeadingToTrailing, null, dicoViews);
NSLayoutConstraint[] buttonToPreventUserInteractionVerticalConstraints = NSLayoutConstraint.FromVisualFormat("V:|[buttonToPreventUserInteraction]|", NSLayoutFormatOptions.DirectionLeadingToTrailing, null, dicoViews);
AddConstraints(buttonToPreventUserInteractionHorizontalConstraints);
AddConstraints(buttonToPreventUserInteractionVerticalConstraints);
}
For your other problem, which is the mouse cursor changing from the content in your superview placed below, you can add a NSTrackingArea on your subview, and implement the override method "MouseMoved" to change the cursor. You can do something like this :
First Add the NSTrackingArea on your subview (you can put this code in your "Initialize" method)
NSTrackingAreaOptions opts = ((NSTrackingAreaOptions.MouseMoved | NSTrackingAreaOptions.ActiveInKeyWindow | NSTrackingAreaOptions.InVisibleRect));
var trackingArea = new NSTrackingArea(new CGRect(0, 0, FittingSize.Width, FittingSize.Height), opts, Self, null);
AddTrackingArea(trackingArea);
And then implement the override method :
public override void MouseMoved(NSEvent theEvent)
{
//You can choose the type of cursor you want to use here
NSCursor.ArrowCursor.Set();
}
This made it for me, hope it will for you too
I´m very new to Xamarin and currently I want to develop a little iOS app that receives data from a REST-Service.
So I have the following Storyboard:
In the table view there should be some entries that are consumed from the REST-Service. When you click on one row you should be "redirected" to a detail view which should be the right View.
The problem is, that the screen of the right story board is just black:
Well let´s have a look at my code, first the FinishedLaunching method in my AppDelegate.cs:
public override void FinishedLaunching(UIApplication application)
{
Window = new UIWindow(UIScreen.MainScreen.Bounds);
UIStoryboard storyboard;
UIViewController initialViewController;
var credential = CredentialController.Instance.FindAccount(CustomStaticLiterals.AppName);
if (credential == null)
{
storyboard = UIStoryboard.FromName("AccountCreationViewController", NSBundle.MainBundle);
initialViewController = storyboard.InstantiateInitialViewController() as UIViewController;
}
else
{
storyboard = UIStoryboard.FromName("OverviewViewController", NSBundle.MainBundle);
initialViewController = storyboard.InstantiateInitialViewController() as UIViewController;
}
Window.RootViewController = initialViewController;
Window.MakeKeyAndVisible();
}
Here is my ProjectOverviewController:
public partial class ProjectOverviewController : UITableViewController
{
public List<Project> Projects { get; set; }
private static readonly NSString callHistoryCellId = new NSString("ProjectCell");
public ProjectOverviewController(IntPtr handle) : base(handle)
{
TableView.RegisterClassForCellReuse(typeof(UITableViewCell), callHistoryCellId);
ProjectOverviewDataSource source = new ProjectOverviewDataSource(this);
source.DetailProjectEvent += DetailProjectPage;
TableView.Source = source;
Projects = new List<Project>();
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
var credentials = CredentialController.Instance.FindAccount(CustomStaticLiterals.AppName);
var service = new ServiceInvoker();
Projects = new List<Project>(service.GetCurrentProjectsOfUserAsync(credentials.UserName).Result);
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
}
void DetailProjectPage(object sender, EventArgs e, int index)
{
var currentProject = Projects[index];
var projectViewController =
Storyboard.InstantiateViewController("ProjectViewController") as ProjectViewController;
if (projectViewController != null)
{
projectViewController.Initialize(currentProject);
NavigationController.PushViewController(projectViewController, true);
}
}
class ProjectOverviewDataSource : UITableViewSource
{
ProjectOverviewController controller;
public delegate void DetailProjectHandler(object sender, EventArgs e, int index);
public event DetailProjectHandler DetailProjectEvent;
public ProjectOverviewDataSource(ProjectOverviewController controller)
{
this.controller = controller;
}
// Returns the number of rows in each section of the table
public override nint RowsInSection(UITableView tableView, nint section)
{
return controller.Projects.Count;
}
//
// Returns a table cell for the row indicated by row property of the NSIndexPath
// This method is called multiple times to populate each row of the table.
// The method automatically uses cells that have scrolled off the screen or creates new ones as necessary.
//
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell(ProjectOverviewController.callHistoryCellId);
int row = indexPath.Row;
cell.TextLabel.Text = controller.Projects[row].Header;
return cell;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
var index = indexPath.Row;
if (DetailProjectEvent != null)
{
DetailProjectEvent(this, new EventArgs(), index);
}
tableView.DeselectRow(indexPath, true);
}
}
}
And finally the the ProjectViewController:
public sealed partial class ProjectViewController : UIPageViewController
{
private Project masterModel;
public ProjectViewController (IntPtr handle) : base (handle)
{
}
public void Initialize(Project masterModel)
{
if (masterModel == null)
{
throw new ArgumentNullException(nameof(masterModel));
}
this.masterModel = masterModel;
}
public override void ViewDidLoad()
{
Title = masterModel.Header;
CustomerField = new UITextField();
CustomerField.Text = masterModel.Customer;
ObjectAddressField = new UITextField();
ObjectAddressField.Text = masterModel.Customer;
}
}
Well there is an other strange behaviour I realized:
When I wanted to set a text for the CustomerField.Text and ObjectAddress.Text property I got a NullReferenceException that the two objects CustomerField and ObjectAddressField are null which leads me to the conclusion that there must a wrong initialization of the ProjectViewController.
If you have some other recommendations about my code, feel free to tell my, because as I said I´m a rookie with Xamarin and App-Development.
I have subclassed UIViewController, which mimics UITableViewController == HUDTableViewController. Then I subclass from this subclassed view controller (SomeViewController : HUDTableViewController).
If I simulate a memory warning, SomeViewController doesn't get released. Here is the code of HUDTableViewController:
using System;
using Foundation;
using UIKit;
namespace MyApp
{
public class HUDTableViewController : UIViewController, IUITableViewDataSource, IUITableViewDelegate, IDisposable, IUIScrollViewDelegate
{
private UIView parentView;
private UITableView tableView;
public UITableView TableView
{
get
{
return this.tableView;
}
set
{
this.tableView = value;
}
}
public HUDTableViewController() : base()
{
Initialize();
}
private void Initialize()
{
this.tableView = new UITableView();
this.tableView.TranslatesAutoresizingMaskIntoConstraints = false;
this.tableView.WeakDelegate = this;
this.tableView.WeakDataSource = this;
this.parentView = new UIView();
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.parentView.AddSubview(this.tableView);
View = this.parentView;
NSMutableDictionary viewsDictionary = new NSMutableDictionary();
viewsDictionary["parent"] = this.parentView;
viewsDictionary["tableView"] = this.tableView;
this.parentView.AddConstraints(NSLayoutConstraint.FromVisualFormat("H:|[tableView]|", (NSLayoutFormatOptions)0, null, viewsDictionary));
this.parentView.AddConstraints(NSLayoutConstraint.FromVisualFormat("V:|[tableView]|", (NSLayoutFormatOptions)0, null, viewsDictionary));
}
[Foundation.Export("numberOfSectionsInTableView:")]
public virtual System.nint NumberOfSections(UIKit.UITableView tableView)
{
return 1;
}
public virtual System.nint RowsInSection(UIKit.UITableView tableview, System.nint section)
{
throw new NotImplementedException();
}
public virtual UIKit.UITableViewCell GetCell(UIKit.UITableView tableView, Foundation.NSIndexPath indexPath)
{
throw new NotImplementedException();
}
[Export("tableView:estimatedHeightForRowAtIndexPath:")]
public virtual System.nfloat EstimatedHeight(UIKit.UITableView tableView, Foundation.NSIndexPath indexPath)
{
return UITableView.AutomaticDimension;
}
[Foundation.Export("tableView:didSelectRowAtIndexPath:")]
public virtual void RowSelected(UIKit.UITableView tableView, Foundation.NSIndexPath indexPath)
{
}
[Export("tableView:heightForRowAtIndexPath:")]
public virtual System.nfloat GetHeightForRow(UIKit.UITableView tableView, Foundation.NSIndexPath indexPath)
{
return 44.0f;
}
[Foundation.Export("tableView:heightForHeaderInSection:")]
public virtual System.nfloat GetHeightForHeader(UIKit.UITableView tableView, System.nint section)
{
return UITableView.AutomaticDimension;
}
[Foundation.Export("tableView:viewForHeaderInSection:")]
public virtual UIKit.UIView GetViewForHeader(UIKit.UITableView tableView, System.nint section)
{
return null;
}
[Export("tableView:titleForHeaderInSection:")]
public virtual string TitleForHeader(UITableView tableView, nint section)
{
return string.Empty;
}
[Foundation.Export("tableView:willDisplayCell:forRowAtIndexPath:")]
public virtual void WillDisplay(UIKit.UITableView tableView, UIKit.UITableViewCell cell, Foundation.NSIndexPath indexPath)
{
}
}
}
tableView should have a reference count of 2 (because of AddSubView and my property).
This is the main view controller, which instantiates SomeViewController:
public class MasterViewContainer : UIViewController
{
private bool hasSetupHandlersAndEvents = false;
// ...
public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
if (!hasSetupHandlersAndEvents) {
if (listButton != null) {
listButton.Clicked += listButton_Clicked;
}
hasSetupHandlersAndEvents = true;
}
}
public override void ViewWillDisappear (bool animated)
{
base.ViewWillDisappear (animated);
if (hasSetupHandlersAndEvents) {
if (listButton != null) {
listButton.Clicked -= listButton_Clicked;
}
hasSetupHandlersAndEvents = false;
}
}
private void listButton_Clicked(object sender, EventArgs args){
SomeViewController viewController = new SomeViewController();
viewController.SomeEvent += SomeEventHandler;
NavigationController.PushViewController(viewController, false);
}
}
As you can see SomeViewController has a reference to MasterViewContainer, because of SomeEventHandler.
SomeViewController is released if I use
public class SomeViewController : UITableViewController
, but it isn't released if I use
public class SomeViewController : HUDTableViewController
The Dispose method is never called. I don't see a reference cycle. Where do I have to release something? What I'm missing?
Try 1:
This is the only solution, which comes to my mind. I use a field (class variable) where I hold the reference to SomeViewController. In DidReceiveMemoryWarning I manually release/dispose it. When I want to access the field, I check if it has been initialised before. If not I initialise it when needed.
public class MasterViewContainer : UIViewController
{
private SomeViewController viewController;
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.
if (this.viewController != null)
{
this.viewController.SomeEvent -= SomeEventHandler;
this.viewController.Dispose();
this.viewController = null;
}
}
private void listButton_Clicked(object sender, EventArgs args){
if (this.viewController == null)
{
this.viewController = new SomeViewController();
this.viewController.SomeEvent += SomeEventHandler;
}
NavigationController.PushViewController(this.viewController, false);
}
But this solution isn't perfect. The dispose is also called when the view is currently on screen. So it is very likely to have malfunctions.
Bounty:
I'd like to have a solution, which explains the memory management issue. Why it doesn't get released? What has to change to get it released (without doing stuff like in my try). It should behave like UITableViewController.
Try 2:
Now I tried to override the Dispose(bool disposing) of HUDTableViewController:
protected override void Dispose(bool disposing)
{
if(!this.disposed)
{
if(disposing)
{
this.tableView.RemoveFromSuperview();
this.tableView.Dispose();
}
this.disposed = true;
}
base.Dispose(disposing);
}
Neither this Dispose method of HUDTableViewController nor the Dispose method of SomeViewController is called.
Call super if you are wanting your parent view to also call the same function handle your management from there. Depending on the arrangement you wouldn't need to do any other manual disposing.
public override void DidReceiveMemoryWarning ()
{
// If you want the superclass to fire the function first call super first
// and vice versa.
super.didReceiveMemoryWarning();
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning ();
I created a class called AddItemBaseAdapter that adds a new row in the ListView. The problem is that when adding a new row, the previous row is deleted. To add a new row I have a editTex and a button on Main.axml. For this case it is better to use ArrayAdapter or BaseAdapter continue using?
AddItemBaseAdapter.cs:
public class AddItemBaseAdapter: BaseAdapter<string>
{
string textReceivedEditText;
Activity context;
public AddItemBaseAdapter(Activity context, string textReceivedEditText) : base()
{
this.context = context;
this.textReceivedEditText = textReceivedEditText;
}
public override long GetItemId(int position){
return position;
}
public override string this[int position] {
get { return textReceivedEditText; }
}
public override int Count {
get { return 1; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView; // re-use an existing view, if one is available
if (view == null)
view = context.LayoutInflater.Inflate (Resource.Layout.newText, null);
view.FindViewById<TextView>(Resource.Id.singleText).Text = textReceivedEditText;
return view;
}
}
OnClick in MainActivity.cs
btnAddNewRow.Click += delegate(object sender, EventArgs e) {
string textFromEditText = FindViewById<EditText> (Resource.Id.editText).Text;
if(!(textFromEditText.Equals(string.Empty)))
{
_HistoryList = FindViewById<ListView>(Resource.Id.TextHistoryList);
_HistoryList.Adapter = new AddItemBaseAdapter(this, textFromEditText);
}
FindViewById<EditText> (Resource.Id.editText).Text = string.Empty;
};
You are creating an entirely new AddItemBaseAdapter every time the button is clicked.
_HistoryList.Adapter = new AddItemBaseAdapter(this, textFromEditText);
Your adapter does not even have the capacity to store more than one item as it stands now. Perhaps try using (or at least studying) the ArrayAdapter class to start. Then if you require futher functionality beyond that, you can extend it or write your own adapter.