How to reload data in UITableView in MonoTouch?

11,753

Solution 1

Pavel is correct - try the following to see if it works:

InvokeOnMainThread(delegate{
    Updates.TableView.Source = source;
    Updates.TableView.AllowsSelection = false;
    Updates.TableView.ReloadData();
});

In future, whenever you're dealing with something that will change the UI currently shown, you will need to ensure that it takes place on the main thread (also known as the GUI thread). This InvokeOnMainThread is a method from NSObject so can be called like above in all UIViews / UIViewControllers etc - you can also call it from an entirely C# class using:

MonoTouch.UIKit.UIApplication.SharedApplication.InvokeOnMainThread(delegate{ /*code here*/ });

Solution 2

You say it is done in a different thread, could it be that the worker thread cannot call the UI thread? I.e. you should call the ReloadData via delegate to be sure it gets called in the UI thread and not "only" in the worker thread, as it might interlock and never get actually called (happened to me in a different scenario).

Solution 3

I also ran into this problem and found this question. Using some of the hint here, I finally got it work by reseting the DataSource and call ReloadView().

tableView.DataSource = new MyDataSource(...);
tableView.RelaodData();

From my testing, it doesn't make different if I wrap the ReloadView() within the InvokeOnMainThread or not. Well, that's maybe because I'm not using worker thread.

It is strange that in another case I could refresh the table view by simply calling ReloadData() in ViewDidAppear(). The only difference is that the above case is the refresh within the same view.

Share:
11,753
Kiril
Author by

Kiril

Updated on June 23, 2022

Comments

  • Kiril
    Kiril almost 2 years

    In my application I display data from a online web service into several UITableViews. I have added several ways for the user to update the data, but the TableView.ReloadData() method does not seem to work. When the user calls for an update, I get a new set of data from the server, pass it to the UITableViewSource instance that is attached to the UITableViewController and then call the ReloadData() method, which unfortunately does not in fact reload the data. Only after I return to the main screen and then go back to the table view (because it is already created, I just display the instance that already exists) does the new data show up in the tableview. What am I doing wrong? I tried creating a new instance of the UITableViewSource when updating the data, but that does not help either.

    Here is the code for loading data into the tableview (I reuse it for any event that requires data to be loaded into it):

     dataControl.GetList(Tables.UPDATES)); //gets data from the server and passes it to the SQL database
     Source source = GetSource(theType.Name, theType, groups); //creates a new source loaded with the data
     Updates.TableView.Source = source;
     Updates.TableView.AllowsSelection = false;     
     Updates.TableView.ReloadData();
    

    This code is of course executed in a separate thread that invokes on the main thread. Basically the same code is called when the user asks for an update(an animation is played while the background thread works).

  • Kiril
    Kiril about 13 years
    Thanks for the reply. I tested this, but it makes no difference. I tried putting all the code in the GUI thread, but that did not work either. I checked to see if ReloadData() gets executed without an interlock, and it does run properly. Is it possible that I need to use some other method to refresh the table view somehow? Maybe invalidate it and force it to be redrawn on the screen?
  • Luke
    Luke about 13 years
    how bizarre. It does sound like a refresh problem. It's a stretch but have you tried TableView.SetNeedsDisplay(); as well?
  • Kiril
    Kiril about 13 years
    Yes, I had tried it and unfortunately it did not result in anything. I have been going through the MonoTouch documentation but so many things are not documented. I could try to pop to the root view controller and then push the reloaded view controller, but first that is a terrible hack and I'd really like to use a better solution, and second it can be confusing for the user (as it takes some time to pop and then push the view controller). Thanks for the help!
  • Luke
    Luke about 13 years
    It could be something to do with the way you're setting your TableView's source. When you pop out of that view and then push the view back on, that would cause ViewWillAppear to be fired - is there anything in that method that you're doing differently to here? p.s. no worries, I'm rather intrigued by this!
  • Kiril
    Kiril about 13 years
    Hi, thanks for the reply. I am not doing anything in the ViewWillAppear. The source I am setting like this: 'Updates.TableView.Source = new USource(some params);' I have tried disposing of the TableView's source/the controller/TableView itself before giving it a new one, but it did not make a difference. I will try to somehow call ViewWillAppear manually to see if that works.
  • Luke
    Luke about 13 years
    What I find helps sometimes is to create a new project and cut out everything unrelated to the problem and attempt to replicate it. If it works, I'd then keep slowly adding bits to it, til it stopped working (then you have a lead on whats causing the havoc) or you're left with an "identical" project that seems to work (which would be most infuriating!)
  • Kiril
    Kiril about 13 years
    No, calling ViewWillAppear manually does not work. I am really baffled at this point. I checked some Objective-C examples on how to do it, and it is supposed to work with just ReloadData().
  • Luke
    Luke about 13 years
    Is it possible to post an example project (even if its just a cut down one which still has the problem) its difficult to debug indepth problems like this remotely!
  • Kiril
    Kiril about 13 years
    Yes, I will do that withing 3-4 hours sorry for the delay.